Refactoring of ScilabException in AST, exec, execstr.
[scilab.git] / scilab / modules / abstractSyntaxTree / 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     T execFunc;
22     std::list<Exp *>::const_iterator    itExp;
23
24     e.name_get().accept(execFunc);
25     if(execFunc.result_get() != NULL && execFunc.result_get()->isCallable())
26     {//function call
27         Callable *pCall = execFunc.result_get()->getAsCallable();
28         types::typed_list out;
29         types::typed_list in;
30
31         //get function arguments
32         T *execVar = new T[e.args_get().size()]();
33         int j = 0;
34         for (j = 0, itExp = e.args_get().begin (); itExp != e.args_get().end (); ++itExp,j++)
35         {
36             (*itExp)->accept (execVar[j]);
37
38             if(execVar[j].result_get() == NULL)
39             {
40                 //special case for empty extraction of list ( list()(:) )
41                 continue;
42             }
43
44             if(execVar[j].result_get()->isImplicitList())
45             {
46                 ImplicitList* pIL = execVar[j].result_get()->getAsImplicitList();
47                 if(pIL->isComputable() == false)
48                 {
49                     Double* pVal = new Double(-1, -1);
50                     pVal->getReal()[0] = 1;
51                     execVar[j].result_set(pVal);
52                 }
53                 else
54                 {
55                     execVar[j].result_set(pIL->extractFullMatrix());
56                 }
57             }
58
59             if(execVar[j].is_single_result())
60             {
61                 in.push_back(execVar[j].result_get());
62                 execVar[j].result_get()->IncreaseRef();
63             }
64             else
65             {
66                 for(int i = 0 ; i < execVar[j].result_getSize() ; i++)
67                 {
68                     in.push_back(execVar[j].result_get(i));
69                     execVar[j].result_get(i)->IncreaseRef();
70                 }
71             }
72         }
73
74         int iRetCount = Max(1, expected_getSize());
75
76         try
77         {
78             T execCall;
79             Function::ReturnValue Ret = pCall->call(in, iRetCount, out, &execCall);
80
81             if(Ret == Callable::OK)
82             {
83                 if(expected_getSize() == 1 && out.size() == 0) //to manage ans
84                 {
85                     if(static_cast<int>(out.size()) < expected_getSize())
86                     {
87                         std::wostringstream os;
88                         os << L"bad lhs, expected : " << expected_getSize() << L" returned : " << out.size() << std::endl;
89                         throw ScilabError(os.str(), 999, e.location_get());
90                     }
91                 }
92
93                 if(out.size() == 1)
94                 {//protect output values
95                     out[0]->IncreaseRef();
96                     result_set(out[0]);
97                 }
98                 else
99                 {
100                     for(int i = 0 ; i < static_cast<int>(out.size()) ; i++)
101                     {//protect output values
102                         out[i]->IncreaseRef();
103                         result_set(i, out[i]);
104                     }
105                 }
106             }
107             else if(Ret == Callable::Error)
108             {
109                 ConfigVariable::setLastErrorFunction(pCall->getName());
110                 ConfigVariable::setLastErrorLine(e.location_get().first_line);
111                 throw ScilabError();
112             }
113
114
115             for (unsigned int k = 0; k < e.args_get().size(); k++)
116             {
117                 if(execVar[k].result_get() != NULL)
118                 {
119                     execVar[k].result_get()->DecreaseRef();
120                 }
121             }
122
123             //std::cout << "before delete[]" << std::endl;
124             delete[] execVar;
125             //std::cout << "after delete[]" << std::endl;
126
127             if(out.size() == 1)
128             {//unprotect output values
129                 out[0]->DecreaseRef();
130             }
131             else
132             {
133                 for(int i = 0 ; i < static_cast<int>(out.size()) ; i++)
134                 {//unprotect output values
135                     out[i]->DecreaseRef();
136                 }
137             }
138         }
139         catch(ScilabMessage sm)
140         {
141             if(pCall->isMacro() || pCall->isMacroFile())
142             {
143                 wchar_t szError[bsiz];
144                 os_swprintf(szError, bsiz, _W("at line % 5d of function %ls called by :\n"), sm.GetErrorLocation().first_line, pCall->getName().c_str());
145                 throw ScilabMessage(szError);
146             }
147             else
148             {
149                 throw sm;
150             }
151         }
152     }
153     else if(execFunc.result_get() != NULL)
154     {//a(xxx) with a variable, extraction
155
156         //get symbol of variable
157         InternalType *pIT = NULL;
158
159         //WARNING can be a fieldexp
160         const SimpleVar *Var = dynamic_cast<const SimpleVar*>(&e.name_get());
161         if(Var != NULL)
162         {
163             pIT = symbol::Context::getInstance()->get(Var->name_get());
164         }
165         else
166         {
167             pIT = execFunc.result_get();
168         }
169
170         int iArgDim = static_cast<int>(e.args_get().size());
171         InternalType *pOut = NULL;
172         std::vector<InternalType*> ResultList;
173
174         //To manage extraction without parameter like SCI()
175         if(iArgDim == 0)
176         {
177             result_set(pIT);
178             return;
179         }
180         else if(pIT->isStruct())
181         {
182             list<wstring> stFields;
183             list<Exp*>::const_iterator it1;
184             for(it1 = e.args_get().begin() ; it1 != e.args_get().end() ; it1++)
185             {
186                 T execArg;
187                 (*it1)->accept(execArg);
188                 if(execArg.result_get()->isString())
189                 {
190                     InternalType* pVar  = execArg.result_get();
191                     String *pString = pVar->getAs<types::String>();
192                     for(int i = 0 ; i < pString->getSize() ; i++)
193                     {
194                         stFields.push_back(pString->get(i));
195                     }
196                 }
197                 else
198                 {//manage error
199                 }
200             }
201
202             ResultList = pIT->getAsStruct()->extract(stFields);
203             for(int i = 0 ; i < static_cast<int>(ResultList.size()) ; i++)
204             {
205                 result_set(i, ResultList[i]);
206             }
207         }
208         else if(pIT->isTList())
209         {
210             list<wstring> stFields;
211             list<Exp*>::const_iterator it1;
212
213             InternalType::RealType rtIndex = InternalType::RealInternal;
214             bool bTypeSet = false;
215             for(it1 = e.args_get().begin() ; it1 != e.args_get().end() ; it1++)
216             {
217                 T execArg;
218                 (*it1)->accept(execArg);
219
220                 if(bTypeSet == true && execArg.result_get()->getType() != rtIndex)
221                 {//TODO: error
222                     YaspWriteW(L"merdouille");
223                 }
224
225                 if(execArg.result_get()->isString())
226                 {
227                     rtIndex = InternalType::RealString;
228                     bTypeSet = true;
229                     InternalType* pVar  = execArg.result_get();
230                     String *pString = pVar->getAs<types::String>();
231                     for(int i = 0 ; i < pString->getSize() ; i++)
232                     {
233                         stFields.push_back(pString->get(i));
234                     }
235                 }
236                 else if(execArg.result_get()->isDouble())
237                 {//manage error
238                     rtIndex = InternalType::RealDouble;
239                     bTypeSet = true;
240                     break;
241                 }
242             }
243
244             if(rtIndex  == InternalType::RealDouble)
245             {
246                 //Create list of indexes
247                 //ArrayOf<double>* pArray = pIT->getAs<ArrayOf<double> >();
248                 //bool bSeeAsVector   = iArgDim < pArray->getDims();
249                 //int *piIndexSeq               = NULL;
250                 //int *piMaxDim       = NULL;
251                 //int *piDimSize                = new int[iArgDim];
252                 //int iDims           = 0;
253                 //int iTotalCombi               = GetIndexList(pIT, e.args_get(), &piIndexSeq, &piMaxDim, &iDims, pIT, piDimSize);
254
255                 ////typed_list *pArgs = GetArgumentList(e.args_get());
256
257                 ////check we don't have bad indexes like "< 1"
258                 //for(int i = 0 ; i < iTotalCombi * iArgDim; i++)
259                 //{
260                 //    if(piIndexSeq[i] < 1)
261                 //    {
262                 //        //manage error
263                 //        std::wostringstream os;
264                 //        os << _W("Indexes must be positive .\n");
265                 //        os << ((Location)e.name_get().location_get()).location_getString() << std::endl;
266                 //        throw ScilabError(os.str(), 999, e.name_get().location_get());
267                 //    }
268                 //}
269                 //ResultList = pIT->getAsTList()->extract(iTotalCombi, piIndexSeq, piMaxDim, iDims, piDimSize, bSeeAsVector);
270             }
271             else if(rtIndex  == InternalType::RealString)
272             {
273                 ResultList = pIT->getAsTList()->extractStrings(stFields);
274             }
275
276             if(ResultList.size() == 1)
277             {
278                 result_set(ResultList[0]);
279             }
280             else
281             {
282                 for(int i = 0 ; i < static_cast<int>(ResultList.size()) ; i++)
283                 {
284                     result_set(i, ResultList[i]);
285                 }
286             }
287         }
288         else
289         {
290             //Create list of indexes
291             typed_list *pArgs = GetArgumentList(e.args_get());
292
293             switch(pIT->getType())
294             {
295             case InternalType::RealDouble :
296                 pOut = pIT->getAs<Double>()->extract(pArgs);
297                 break;
298             case InternalType::RealString :
299                 pOut = pIT->getAs<String>()->extract(pArgs);
300                 break;
301             case InternalType::RealBool :
302                 pOut = pIT->getAs<Bool>()->extract(pArgs);
303                 break;
304             case InternalType::RealPoly :
305                 pOut = pIT->getAs<Polynom>()->extract(pArgs);
306                 break;
307             case InternalType::RealInt8 :
308                 pOut = pIT->getAs<Int8>()->extract(pArgs);
309                 break;
310             case InternalType::RealUInt8 :
311                 pOut = pIT->getAs<UInt8>()->extract(pArgs);
312                 break;
313             case InternalType::RealInt16 :
314                 pOut = pIT->getAs<Int16>()->extract(pArgs);
315                 break;
316             case InternalType::RealUInt16 :
317                 pOut = pIT->getAs<UInt16>()->extract(pArgs);
318                 break;
319             case InternalType::RealInt32 :
320                 pOut = pIT->getAs<Int32>()->extract(pArgs);
321                 break;
322             case InternalType::RealUInt32 :
323                 pOut = pIT->getAs<UInt32>()->extract(pArgs);
324                 break;
325             case InternalType::RealInt64 :
326                 pOut = pIT->getAs<Int64>()->extract(pArgs);
327                 break;
328             case InternalType::RealUInt64 :
329                 pOut = pIT->getAs<UInt64>()->extract(pArgs);
330                 break;
331             case InternalType::RealList :
332                 {
333                     ResultList = pIT->getAsList()->extract(pArgs);
334
335                     switch(ResultList.size())
336                     {
337                     case 0 :
338                         {
339                             //std::wostringstream os;
340                             //os << L"inconsistent dimensions\n";
341                             //throw ScilabError(os.str(), 999, (*e.args_get().begin())->location_get());
342                             result_set(NULL);
343                         }
344                         break;
345                     case 1 :
346                         result_set(ResultList[0]);
347                         break;
348                     default :
349                         for(int i = 0 ; i < static_cast<int>(ResultList.size()) ; i++)
350                         {
351                             result_set(i, ResultList[i]);
352                         }
353                         break;
354                     }
355                 }
356                 break;
357             case InternalType::RealCell :
358                 pOut = pIT->getAs<Cell>()->extract(pArgs);
359                 break;
360             default :
361                 break;
362             }
363         }
364
365         //List extraction can return multiple items
366         if(pIT->isList() == false && pIT->isStruct() == false && pIT->isTList() == false)
367         {
368             if(pOut == NULL)
369             {
370                 // Special case, try to extract from an empty matrix.
371                 if (pIT->isDouble() && pIT->getAs<Double>()->getSize() == 0)
372                 {
373                     pOut = Double::Empty();
374                 }
375                 else
376                 {
377                     std::wostringstream os;
378                     os << L"Invalid index\n";
379                     //os << ((*e.args_get().begin())->location_get()).location_getString() << std::endl;
380                     throw ScilabError(os.str(), 999, (*e.args_get().begin())->location_get());
381                 }
382             }
383             result_set(pOut);
384         }
385         else
386         {
387             if(ResultList.size() == 0)
388             {
389                 if(pIT->isList())
390                 {
391                     result_set(NULL);
392                 }
393                 else
394                 {
395                     std::wostringstream os;
396                     os << L"inconsistent row/column dimensions\n";
397                     //os << ((*e.args_get().begin())->location_get()).location_getString() << std::endl;
398                     throw ScilabError(os.str(), 999, (*e.args_get().begin())->location_get());
399                 }
400             }
401         }
402     }
403     else
404     {
405         //result == NULL ,variable doesn't exist :(
406         // Sould never be in this case
407         // In worst case variable pointing to function does not exists
408         // visitprivate(SimpleVar) will throw the right exception.
409     }
410 }