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