manage a=42 in parameter of macro
[scilab.git] / scilab / modules / ast / includes / run_CallExp.hxx
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2010-2010 - DIGITEO - Bruno JOFRET
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 // This code is separated in run_CallExp.hxx
14 // but will be inlined in runvisitor.hxx
15 // using #include with RunVisitorT class declaration.
16 //
17 // If you need additionnal headers, please add it in runvisitor.hxx
18
19 void visitprivate(const CallExp &e)
20 {
21     std::list<Exp *>::const_iterator    itExp;
22
23     e.name_get().accept(*this);
24     if (result_get() != NULL && result_get()->isCallable())
25     {
26         //function call
27         types::InternalType* pIT = result_get();
28         types::Callable *pCall = pIT->getAs<types::Callable>();
29         types::typed_list out;
30         types::typed_list in;
31         types::optional_list opt;
32
33         int iRetCount = expected_getSize();
34
35         //get function arguments
36         for (itExp = e.args_get().begin (); itExp != e.args_get().end (); ++itExp)
37         {
38             AssignExp* pAssign = dynamic_cast<AssignExp*>(*itExp);
39             if (pAssign)
40             {
41                 //optional parameter
42                 Exp* pL = &pAssign->left_exp_get();
43                 SimpleVar* pVar = dynamic_cast<SimpleVar*>(pL);
44                 if (pVar == NULL)
45                 {
46                     std::wostringstream os;
47                     os << _W("left side of optional parameter must be a variable") << std::endl;
48                     throw ScilabError(os.str(), 999, e.location_get());
49                 }
50
51                 Exp* pR = &pAssign->right_exp_get();
52                 pR->accept (*this);
53                 InternalType* pITR = result_get();
54
55                 opt.push_back(std::pair<std::wstring, InternalType*>(pVar->name_get().name_get(), pITR));
56                 //in case of macro/macrofile, we have to shift input param
57                 //so add NULL item in in list to keep initial order
58                 if (pIT->isMacro() || pIT->isMacroFile())
59                 {
60                     in.push_back(NULL);
61                 }
62                 continue;
63             }
64
65             expected_size_set(1);
66             (*itExp)->accept (*this);
67
68             if (result_get() == NULL)
69             {
70                 //special case for empty extraction of list ( list()(:) )
71                 continue;
72             }
73
74             pIT = result_get();
75             if (result_get()->isImplicitList())
76             {
77                 types::ImplicitList* pIL = pIT->getAs<types::ImplicitList>();
78                 if (pIL->isComputable() == false)
79                 {
80                     types::Double* pVal = new types::Double(-1, -1);
81                     pVal->getReal()[0] = 1;
82                     result_set(pVal);
83                 }
84                 else
85                 {
86                     result_set(pIL->extractFullMatrix());
87                 }
88             }
89
90             if (is_single_result())
91             {
92                 in.push_back(result_get());
93                 result_get()->IncreaseRef();
94             }
95             else
96             {
97                 for (int i = 0 ; i < result_getSize() ; i++)
98                 {
99                     in.push_back(result_get(i));
100                     result_get(i)->IncreaseRef();
101                 }
102             }
103         }
104
105         try
106         {
107             int iSaveExpectedSize = iRetCount;
108             expected_size_set(iSaveExpectedSize);
109             iRetCount = Max(1, iRetCount);
110
111             //reset previous error before call function
112             ConfigVariable::resetError();
113             //update verbose";" flag
114             ConfigVariable::setVerbose(e.is_verbose());
115             //call function
116             types::Function::ReturnValue Ret = pCall->call(in, opt, iRetCount, out, this);
117             expected_size_set(iSaveExpectedSize);
118             result_clear();
119
120             if (Ret == types::Callable::OK)
121             {
122                 if (expected_getSize() == 1 && out.size() == 0) //some function have no returns
123                 {
124                     if (static_cast<int>(out.size()) < iRetCount)
125                     {
126                         //clear input parameters
127                         for (unsigned int k = 0; k < in.size(); k++)
128                         {
129                             if (in[k] == NULL)
130                             {
131                                 continue;
132                             }
133
134                             in[k]->DecreaseRef();
135                             if (in[k]->isDeletable())
136                             {
137                                 delete in[k];
138                             }
139                         }
140
141                         std::wostringstream os;
142                         os << _W("bad lhs, expected : ") << iRetCount << _W(" returned : ") << out.size() << std::endl;
143                         throw ScilabError(os.str(), 999, e.location_get());
144                     }
145                 }
146
147                 if (out.size() == 1)
148                 {
149                     result_set(out[0]);
150                 }
151                 else
152                 {
153                     for (int i = 0 ; i < static_cast<int>(out.size()) ; i++)
154                     {
155                         result_set(i, out[i]);
156                     }
157                 }
158             }
159             else if (Ret == types::Callable::Error)
160             {
161                 ConfigVariable::setLastErrorFunction(pCall->getName());
162                 ConfigVariable::setLastErrorLine(e.location_get().first_line);
163                 throw ScilabError();
164             }
165         }
166         catch (ScilabMessage sm)
167         {
168             //clear input parameters
169             for (unsigned int k = 0; k < in.size(); k++)
170             {
171                 if (in[k] && in[k]->isDeletable())
172                 {
173                     delete in[k];
174                 }
175             }
176
177             if (pCall->isMacro() || pCall->isMacroFile())
178             {
179                 wchar_t szError[bsiz];
180                 os_swprintf(szError, bsiz, _W("at line % 5d of function %ls called by :\n"), sm.GetErrorLocation().first_line, pCall->getName().c_str());
181                 throw ScilabMessage(szError);
182             }
183             else
184             {
185                 throw sm;
186             }
187         }
188
189         //clear input parameters but take care in case of in[k] == out[i]
190         for (unsigned int k = 0; k < in.size(); k++)
191         {
192             if (in[k] == NULL)
193             {
194                 continue;
195             }
196
197             //check if input data are use as output data
198             bool bFind = false;
199             for (int i = 0 ; i < out.size() ; i++)
200             {
201                 if (out[i] == in[k])
202                 {
203                     bFind = true;
204                     break;
205                 }
206             }
207
208             in[k]->DecreaseRef();
209             if (bFind == false)
210             {
211                 if (in[k]->isDeletable())
212                 {
213                     delete in[k];
214                 }
215             }
216         }
217     }
218     else if (result_get() != NULL)
219     {
220         //a(xxx) with a variable, extraction
221
222         //get symbol of variable
223         types::InternalType *pIT = NULL;
224
225         //WARNING can be a fieldexp
226         const SimpleVar *Var = dynamic_cast<const SimpleVar*>(&e.name_get());
227         if (Var != NULL)
228         {
229             pIT = symbol::Context::getInstance()->get(Var->name_get());
230         }
231         else
232         {
233             pIT = result_get();
234         }
235
236         int iArgDim = static_cast<int>(e.args_get().size());
237         types::InternalType *pOut = NULL;
238         std::vector<types::InternalType*> ResultList;
239
240         //To manage extraction without parameter like SCI()
241         if (iArgDim == 0)
242         {
243             result_set(pIT);
244             return;
245         }
246         else
247         {
248             //Create list of indexes
249             types::typed_list *pArgs = GetArgumentList(e.args_get());
250
251             switch (pIT->getType())
252             {
253                 case types::InternalType::RealDouble :
254                     pOut = pIT->getAs<types::Double>()->extract(pArgs);
255                     break;
256                 case types::InternalType::RealString :
257                     pOut = pIT->getAs<types::String>()->extract(pArgs);
258                     break;
259                 case types::InternalType::RealBool :
260                     pOut = pIT->getAs<types::Bool>()->extract(pArgs);
261                     break;
262                 case types::InternalType::RealPoly :
263                     pOut = pIT->getAs<types::Polynom>()->extract(pArgs);
264                     break;
265                 case types::InternalType::RealInt8 :
266                     pOut = pIT->getAs<types::Int8>()->extract(pArgs);
267                     break;
268                 case types::InternalType::RealUInt8 :
269                     pOut = pIT->getAs<types::UInt8>()->extract(pArgs);
270                     break;
271                 case types::InternalType::RealInt16 :
272                     pOut = pIT->getAs<types::Int16>()->extract(pArgs);
273                     break;
274                 case types::InternalType::RealUInt16 :
275                     pOut = pIT->getAs<types::UInt16>()->extract(pArgs);
276                     break;
277                 case types::InternalType::RealInt32 :
278                     pOut = pIT->getAs<types::Int32>()->extract(pArgs);
279                     break;
280                 case types::InternalType::RealUInt32 :
281                     pOut = pIT->getAs<types::UInt32>()->extract(pArgs);
282                     break;
283                 case types::InternalType::RealInt64 :
284                     pOut = pIT->getAs<types::Int64>()->extract(pArgs);
285                     break;
286                 case types::InternalType::RealUInt64 :
287                     pOut = pIT->getAs<types::UInt64>()->extract(pArgs);
288                     break;
289                 case types::InternalType::RealList :
290                 {
291                     ResultList = pIT->getAs<types::List>()->extract(pArgs);
292
293                     switch (ResultList.size())
294                     {
295                         case 0 :
296                         {
297                             result_set(NULL);
298                         }
299                         break;
300                         case 1 :
301                             result_set(ResultList[0]);
302                             break;
303                         default :
304                             for (int i = 0 ; i < static_cast<int>(ResultList.size()) ; i++)
305                             {
306                                 result_set(i, ResultList[i]);
307                             }
308                             break;
309                     }
310                 }
311                 break;
312                 case InternalType::RealTList :
313                 {
314                     bool bCallOverLoad = false;
315                     if (pArgs->size() == 1)
316                     {
317                         types::InternalType* pArg = (*pArgs)[0];
318                         if ( pArg->isDouble() ||
319                                 pArg->isInt() ||
320                                 pArg->isBool() ||
321                                 pArg->isImplicitList() ||
322                                 pArg->isColon() ||
323                                 pArg->isDollar())
324
325                         {
326                             //call "normal" extract
327                             typed_list iField;
328                             iField.push_back(pArg);
329                             ResultList = pIT->getAs<TList>()->extract(&iField);
330                         }
331                         else if (pArg->isString())
332                         {
333                             //extractStrings
334                             list<wstring> stFields;
335                             String *pString = (*pArgs)[0]->getAs<types::String>();
336                             for (int i = 0 ; i < pString->getSize() ; i++)
337                             {
338                                 stFields.push_back(pString->get(i));
339                             }
340
341                             ResultList = pIT->getAs<TList>()->extractStrings(stFields);
342                             if (ResultList.empty())
343                             {
344                                 bCallOverLoad = true;
345                             }
346                         }
347                         else
348                         {
349                             bCallOverLoad = true;
350                         }
351                     }
352                     else
353                     {
354                         bCallOverLoad = true;
355                     }
356
357                     if (bCallOverLoad)
358                     {
359                         types::typed_list in;
360
361                         //create input argument list
362
363                         //protect inputs
364                         for (int i = 0 ; i < pArgs->size() ; i++)
365                         {
366                             (*pArgs)[i]->IncreaseRef();
367                             in.push_back((*pArgs)[i]);
368                         }
369
370                         //protect TList
371                         pIT->IncreaseRef();
372                         in.push_back(pIT);
373
374                         try
375                         {
376                             //try to call specific exrtaction function
377                             Overload::call(L"%" + pIT->getAs<TList>()->getShortTypeStr() + L"_e", in, 1, ResultList, this);
378                         }
379                         catch (ScilabError /*&e*/)
380                         {
381                             //if call failed try to call generic extraction function
382                             Overload::call(L"%l_e", in, 1, ResultList, this);
383                         }
384
385                         for (int i = 0 ; i < pArgs->size() ; i++)
386                         {
387                             (*pArgs)[i]->DecreaseRef();
388                         }
389                         pIT->DecreaseRef();
390                     }
391
392                     switch (ResultList.size())
393                     {
394                         case 0 :
395                         {
396                             std::wostringstream os;
397                             os << _W("Invalid index.\n");
398                             throw ScilabError(os.str(), 999, (*e.args_get().begin())->location_get());
399                         }
400                         break;
401                         case 1 :
402                             result_set(ResultList[0]);
403                             break;
404                         default :
405                             for (int i = 0 ; i < static_cast<int>(ResultList.size()) ; i++)
406                             {
407                                 result_set(i, ResultList[i]);
408                             }
409                             break;
410                     }
411                     break;
412                 }
413                 case InternalType::RealMList :
414                 {
415                     bool bCallOverLoad = false;
416                     if (pArgs->size() == 1)
417                     {
418                         types::InternalType* pArg = (*pArgs)[0];
419                         if (pArg->isString())
420                         {
421                             //extractStrings
422                             list<wstring> stFields;
423                             String *pString = (*pArgs)[0]->getAs<types::String>();
424                             for (int i = 0 ; i < pString->getSize() ; i++)
425                             {
426                                 stFields.push_back(pString->get(i));
427                             }
428
429                             ResultList = pIT->getAs<MList>()->extractStrings(stFields);
430                             if (ResultList.empty())
431                             {
432                                 bCallOverLoad = true;
433                             }
434                         }
435                         else
436                         {
437                             bCallOverLoad = true;
438                         }
439                     }
440                     else
441                     {
442                         bCallOverLoad = true;
443                     }
444
445                     if (bCallOverLoad)
446                     {
447                         types::typed_list in;
448
449                         //create input argument list
450
451                         //protect inputs
452                         for (int i = 0 ; i < pArgs->size() ; i++)
453                         {
454                             (*pArgs)[i]->IncreaseRef();
455                             in.push_back((*pArgs)[i]);
456                         }
457
458                         //protect TList
459                         pIT->IncreaseRef();
460                         in.push_back(pIT);
461
462                         try
463                         {
464                             //try to call specific exrtaction function
465                             Overload::call(L"%" + pIT->getAs<MList>()->getShortTypeStr() + L"_e", in, 1, ResultList, this);
466                         }
467                         catch (ScilabError /*&e*/)
468                         {
469                             //if call failed try to call generic extraction function
470                             Overload::call(L"%l_e", in, 1, ResultList, this);
471                         }
472
473                         for (int i = 0 ; i < pArgs->size() ; i++)
474                         {
475                             (*pArgs)[i]->DecreaseRef();
476                         }
477                         pIT->DecreaseRef();
478                     }
479
480                     switch (ResultList.size())
481                     {
482                         case 0 :
483                         {
484                             std::wostringstream os;
485                             os << _W("Invalid index.\n");
486                             throw ScilabError(os.str(), 999, (*e.args_get().begin())->location_get());
487                         }
488                         break;
489                         case 1 :
490                             result_set(ResultList[0]);
491                             break;
492                         default :
493                             for (int i = 0 ; i < static_cast<int>(ResultList.size()) ; i++)
494                             {
495                                 result_set(i, ResultList[i]);
496                             }
497                             break;
498                     }
499                     break;
500                 }
501                 case InternalType::RealCell :
502                     pOut = pIT->getAs<Cell>()->extract(pArgs);
503                     break;
504                 case types::InternalType::RealSparse :
505                     pOut = pIT->getAs<types::Sparse>()->extract(pArgs);
506                     break;
507                 case types::InternalType::RealSparseBool :
508                     pOut = pIT->getAs<types::SparseBool>()->extract(pArgs);
509                     break;
510                 case types::InternalType::RealStruct :
511                 {
512                     types::Struct* pStr = pIT->getAs<types::Struct>();
513                     if (pArgs->size() == 1 && (*pArgs)[0]->isString())
514                     {
515                         //s(["x","xx"])
516                         std::list<wstring> wstFields;
517                         types::String *pS = (*pArgs)[0]->getAs<types::String>();
518                         for (int i = 0 ; i < pS->getSize() ; i++)
519                         {
520                             wstring wstField(pS->get(i));
521                             if (pStr->exists(wstField))
522                             {
523                                 wstFields.push_back(wstField);
524                             }
525                             else
526                             {
527                                 wchar_t szError[bsiz];
528                                 os_swprintf(szError, bsiz, _W("Field \"%ls\" does not exists\n"), wstField.c_str());
529                                 throw ScilabError(szError, 999, (*e.args_get().begin())->location_get());
530                             }
531                         }
532
533                         ResultList = pStr->extractFields(wstFields);
534                         if (ResultList.size() == 1 && ResultList[0]->getAs<types::List>()->getSize() == 1)
535                         {
536                             result_set(ResultList[0]->getAs<types::List>()->get(0));
537                         }
538                         else
539                         {
540                             for (int i = 0 ; i < static_cast<int>(ResultList.size()) ; i++)
541                             {
542                                 result_set(i, ResultList[i]);
543                             }
544                         }
545                         return;
546                     }
547                     else
548                     {
549                         pOut = pIT->getAs<types::Struct>()->extract(pArgs);
550                     }
551                     break;
552                 }
553                 case types::InternalType::RealHandle :
554                 {
555                     if (pArgs->size() == 1 && (*pArgs)[0]->isString())
556                     {
557                         //s(["x"])
558                         types::GraphicHandle* pH = pIT->getAs<types::GraphicHandle>();
559                         types::String *pS = (*pArgs)[0]->getAs<types::String>();
560                         typed_list in;
561                         typed_list out;
562                         optional_list opt;
563
564                         in.push_back(pS);
565                         in.push_back(pH);
566
567                         Function* pCall = (Function*)symbol::Context::getInstance()->get(symbol::Symbol(L"%h_e"));
568                         Callable::ReturnValue ret =  pCall->call(in, opt, 1, out, this);
569                         if (ret == Callable::OK)
570                         {
571                             pOut = out[0];
572                         }
573                     }
574                     else
575                     {
576                         pOut = pIT->getAs<types::GraphicHandle>()->extract(pArgs);
577                     }
578                     break;
579                 }
580                 default :
581                     break;
582             }
583
584             //clean pArgs return by GetArgumentList
585             for (int iArg = 0 ; iArg < pArgs->size() ; iArg++)
586             {
587                 if ((*pArgs)[iArg]->isDeletable())
588                 {
589                     delete (*pArgs)[iArg];
590                 }
591             }
592             delete pArgs;
593         }
594
595         //List extraction can return multiple items
596         if (pIT->isList() == false && pIT->isTList() == false)
597         {
598             if (pOut == NULL)
599             {
600                 // Special case, try to extract from an empty matrix.
601                 if (pIT->isDouble() && pIT->getAs<types::Double>()->getSize() == 0)
602                 {
603                     pOut = types::Double::Empty();
604                 }
605                 else
606                 {
607                     std::wostringstream os;
608                     os << _W("Invalid index.\n");
609                     //os << ((*e.args_get().begin())->location_get()).location_getString() << std::endl;
610                     throw ScilabError(os.str(), 999, (*e.args_get().begin())->location_get());
611                 }
612             }
613             result_set(pOut);
614         }
615         else
616         {
617             if (ResultList.size() == 0)
618             {
619                 if (pIT->isList())
620                 {
621                     result_set(NULL);
622                 }
623                 else
624                 {
625                     std::wostringstream os;
626                     os << _W("inconsistent row/column dimensions\n");
627                     //os << ((*e.args_get().begin())->location_get()).location_getString() << std::endl;
628                     throw ScilabError(os.str(), 999, (*e.args_get().begin())->location_get());
629                 }
630             }
631         }
632     }
633     else
634     {
635         //result == NULL ,variable doesn't exist :(
636         // Sould never be in this case
637         // In worst case variable pointing to function does not exists
638         // visitprivate(SimpleVar) will throw the right exception.
639     }
640 }
641
642 void visitprivate(const CellCallExp &e)
643 {
644     //get head
645     T execMeCell;
646     e.name_get().accept(execMeCell);
647
648     if (execMeCell.result_get() != NULL)
649     {
650         //a{xxx} with a variable, extraction
651         types::InternalType *pIT = NULL;
652
653         pIT = execMeCell.result_get();
654
655         if (pIT)
656         {
657
658             if (pIT->isCell() == false)
659             {
660                 throw ScilabError(_W("[error] Cell contents reference from a non-cell array object.\n"), 999, (*e.args_get().begin())->location_get());
661             }
662             //Create list of indexes
663             types::typed_list *pArgs = GetArgumentList(e.args_get());
664
665             types::List* pList = pIT->getAs<types::Cell>()->extractCell(pArgs);
666
667             if (pList == NULL)
668             {
669                 std::wostringstream os;
670                 os << _W("inconsistent row/column dimensions\n");
671                 //os << ((*e.args_get().begin())->location_get()).location_getString() << std::endl;
672                 throw ScilabError(os.str(), 999, (*e.args_get().begin())->location_get());
673             }
674
675             if (pList->getSize() == 1)
676             {
677                 result_set(pList->get(0));
678             }
679             else
680             {
681                 result_set(pList);
682             }
683
684             //clean pArgs return by GetArgumentList
685             for (int iArg = 0 ; iArg < pArgs->size() ; iArg++)
686             {
687                 if ((*pArgs)[iArg]->isDeletable())
688                 {
689                     delete (*pArgs)[iArg];
690                 }
691             }
692             delete pArgs;
693         }
694     }
695     else
696     {
697         //result == NULL ,variable doesn't exist :(
698         // Sould never be in this case
699         // In worst case variable pointing to function does not exists
700         // visitprivate(SimpleVar) will throw the right exception.
701     }
702 }