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