Refactoring of ScilabException in AST, exec, execstr.
[scilab.git] / scilab / modules / abstractSyntaxTree / src / cpp / visitor_common.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2010-2010 - DIGITEO - Antoine ELIAS
4 *
5 *  This file must be used under the terms of the CeCILL.
6 *  This source file is licensed as described in the file COPYING, which
7 *  you should have received as part of this distribution.  The terms
8 *  are also available at
9 *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10 *
11 */
12
13 #include <string>
14 #include <numeric>
15 #include "visitor_common.hxx"
16 #include "exp.hxx"
17 #include "fieldexp.hxx"
18 #include "simplevar.hxx"
19 #include "callexp.hxx"
20 #include "struct.hxx"
21 #include "context.hxx"
22 #include "execvisitor.hxx"
23
24 #include "alltypes.hxx"
25
26 bool bConditionState(types::InternalType *_pITResult)
27 {
28         if(_pITResult->isDouble() &&
29         _pITResult->getAs<types::Double>()->isComplex() == false)
30         {
31                 types::Double *pR = _pITResult->getAs<types::Double>();
32         if(pR->isEmpty())
33         {//[]
34             return false;
35         }
36
37                 double *pReal = pR->getReal();
38                 for(int i = 0 ; i < pR->getSize() ; i++)
39                 {
40                         if(pReal[i] == 0)
41                         {
42                                 return false;
43                         }
44                 }
45         }
46         else if(_pITResult->isBool())
47         {
48                 types::Bool *pB         = _pITResult->getAs<types::Bool>();
49                 int *piData     = pB->get();
50
51                 for(int i = 0 ; i < pB->getSize() ; i++)
52                 {
53                         if(piData[i] == 0)
54                         {
55                                 return false;
56                                 break;
57                         }
58                 }
59         }
60         else if(_pITResult->isInt())
61         {
62         }
63         else
64         {
65                 return false;
66         }
67         return true;
68 }
69
70 /*
71  * Generate destination variable from _poSource type and size parameters
72  */
73 types::InternalType* allocDest(types::InternalType* _poSource, int _iRows, int _iCols)
74 {
75     types::InternalType* poResult = NULL;
76     switch(_poSource->getType())
77     {
78     case types::GenericType::RealDouble :
79         poResult = new types::Double(_iRows, _iCols, false);
80         break;
81     case types::GenericType::RealBool :
82         poResult = new types::Bool(_iRows, _iCols);
83         break;
84     case types::GenericType::RealInt8 :
85         poResult = new types::Int8(_iRows, _iCols);
86         break;
87     case types::GenericType::RealUInt8 :
88         poResult = new types::UInt8(_iRows, _iCols);
89         break;
90     case types::GenericType::RealInt16 :
91         poResult = new types::Int16(_iRows, _iCols);
92         break;
93     case types::GenericType::RealUInt16 :
94         poResult = new types::UInt16(_iRows, _iCols);
95         break;
96     case types::GenericType::RealInt32 :
97         poResult = new types::Int32(_iRows, _iCols);
98         break;
99     case types::GenericType::RealUInt32 :
100         poResult = new types::UInt32(_iRows, _iCols);
101         break;
102     case types::GenericType::RealInt64 :
103         poResult = new types::Int64(_iRows, _iCols);
104         break;
105     case types::GenericType::RealUInt64 :
106         poResult = new types::UInt64(_iRows, _iCols);
107         break;
108     case types::GenericType::RealString :
109         poResult = new types::String(_iRows, _iCols);
110         break;
111     case types::GenericType::RealPoly :
112         {
113             int* piRank = new int[_iRows * _iCols];
114             for(int i = 0 ; i < _iRows * _iCols ; i++)
115             {
116                 piRank[i] = 1;
117             }
118             poResult = new types::Polynom(_poSource->getAs<types::Polynom>()->getVariableName(), _iRows, _iCols, piRank);
119             break;
120         }
121     case types::InternalType::RealImplicitList :
122         poResult = new types::ImplicitList();
123         break;
124     default :
125         // FIXME : What should we do here ??
126         break;
127     }
128     return poResult;
129 }
130
131 types::InternalType* AddElementToVariableFromCol(types::InternalType* _poDest, types::InternalType* _poSource, int _iRows, int _iCols, int *_piCols)
132 {
133     types::InternalType *poResult                   = NULL;
134     types::InternalType::RealType TypeSource    = _poSource->getType();
135     types::InternalType::RealType TypeDest              = types::InternalType::RealInternal;
136     int iCurRow                                 = _iRows;
137     int iCurCol                                 = _iCols;
138
139
140     if(_poDest == NULL)
141     {//First call, alloc _poSource
142         poResult    = allocDest(_poSource, _iRows, _iCols);
143         TypeDest        = TypeSource;
144         iCurCol     = 0;
145         iCurRow         = 0;
146     }
147     else
148     {
149         TypeDest    = _poDest->getType();
150         poResult    = _poDest;
151     }
152
153     if(TypeDest != TypeSource)
154     {//check if source type is compatible with dest type
155     }
156     else
157     {
158         switch(TypeDest)
159         {
160         case types::GenericType::RealDouble :
161             if(poResult->getAs<types::Double>()->isComplex() == false && _poSource->getAs<types::Double>()->isComplex() == true)
162             {
163                 poResult->getAs<types::Double>()->setComplex(true);
164             }
165
166             poResult->getAs<types::Double>()->fillFromCol(*_piCols, _poSource->getAs<types::Double>());
167             *_piCols += _poSource->getAs<types::Double>()->getCols();
168
169             break;
170         default:
171             break;
172         }
173         return poResult;
174     }
175     return NULL;
176 }
177
178 types::InternalType* AddElementToVariableFromRow(types::InternalType* _poDest, types::InternalType* _poSource, int _iRows, int _iCols, int *_piRows)
179 {
180         types::InternalType *poResult               = NULL;
181         types::InternalType::RealType TypeSource        = _poSource->getType();
182         types::InternalType::RealType TypeDest          = types::InternalType::RealInternal;
183         int iCurRow                                 = _iRows;
184         int iCurCol                                 = _iCols;
185
186     if(_poDest == NULL)
187     {//First call, alloc _poSource
188         poResult    = allocDest(_poSource, _iRows, _iCols);
189         iCurCol     = 0;
190         iCurRow         = 0;
191         TypeDest        = TypeSource;
192     }
193     else
194     {
195         TypeDest        = _poDest->getType();
196         poResult    = _poDest;
197     }
198
199
200     if(TypeDest != TypeSource)
201     {//check if source type is compatible with dest type
202     }
203     else
204     {
205         switch(TypeDest)
206         {
207         case types::GenericType::RealDouble :
208             if(poResult->getAs<types::Double>()->isComplex() == false && _poSource->getAs<types::Double>()->isComplex() == true)
209             {
210                 poResult->getAs<types::Double>()->setComplex(true);
211             }
212
213             poResult->getAs<types::Double>()->fillFromRow(*_piRows, _poSource->getAs<types::Double>());
214             *_piRows += _poSource->getAs<types::Double>()->getRows();
215
216             break;
217         default:
218             break;
219         }
220         return poResult;
221     }
222     return NULL;
223 }
224
225
226 /*
227 _iRows : Position if _poDest allready initialized else size of the matrix
228 _iCols : Position if _poDest allready initialized else size of the matrix
229 */
230 types::InternalType* AddElementToVariable(types::InternalType* _poDest, types::InternalType* _poSource, int _iRows, int _iCols, int *_piRows, int *_piCols)
231 {
232         types::InternalType *poResult   = NULL;
233         types::InternalType::RealType TypeSource        = _poSource->getType();
234         types::InternalType::RealType TypeDest          =       types::InternalType::RealInternal;
235         int iCurRow = _iRows;
236         int iCurCol = _iCols;
237
238         if(_poDest == NULL)
239         {
240                 switch(TypeSource)
241                 {
242                 case types::GenericType::RealDouble :
243                         poResult = new types::Double(_iRows, _iCols, false);
244                         break;
245                 case types::GenericType::RealBool :
246                         poResult = new types::Bool(_iRows, _iCols);
247                         break;
248         case types::GenericType::RealInt8 :
249             poResult = new types::Int8(_iRows, _iCols);
250             break;
251         case types::GenericType::RealUInt8 :
252             poResult = new types::UInt8(_iRows, _iCols);
253             break;
254         case types::GenericType::RealInt16 :
255             poResult = new types::Int16(_iRows, _iCols);
256             break;
257         case types::GenericType::RealUInt16 :
258             poResult = new types::UInt16(_iRows, _iCols);
259             break;
260         case types::GenericType::RealInt32 :
261             poResult = new types::Int32(_iRows, _iCols);
262             break;
263         case types::GenericType::RealUInt32 :
264             poResult = new types::UInt32(_iRows, _iCols);
265             break;
266         case types::GenericType::RealInt64 :
267             poResult = new types::Int64(_iRows, _iCols);
268             break;
269         case types::GenericType::RealUInt64 :
270             poResult = new types::UInt64(_iRows, _iCols);
271             break;
272                 case types::GenericType::RealString :
273                         poResult = new types::String(_iRows, _iCols);
274                         break;
275                 case types::GenericType::RealPoly :
276                         {
277                                 int* piRank = new int[_iRows * _iCols];
278                                 for(int i = 0 ; i < _iRows * _iCols ; i++)
279                                 {
280                                         piRank[i] = 1;
281                                 }
282                                 poResult = new types::Polynom(_poSource->getAs<types::Polynom>()->getVariableName(), _iRows, _iCols, piRank);
283                                 break;
284                         }
285                 case types::InternalType::RealImplicitList :
286                         poResult = new types::ImplicitList();
287                         break;
288         default :
289             // FIXME What should we do here ...
290             break;
291                 }
292                 iCurCol         = 0;
293                 iCurRow         = 0;
294                 TypeDest        =       TypeSource;
295         }
296         else
297         {
298                 TypeDest                = _poDest->getType();
299                 poResult = _poDest;
300         }
301
302
303         if(TypeDest != TypeSource)
304         {//check if source type is compatible with dest type
305                 switch(TypeDest)
306                 {
307                 case types::GenericType::RealDouble :
308                         if(TypeSource == types::GenericType::RealPoly)
309                         {
310                                 types::Double *poDest = _poDest->getAs<types::Double>();
311                                 //Convert Dest to RealPoly
312                                 int *piRank = new int[poDest->getSize()];
313                                 for(int i = 0 ; i < poDest->getSize() ; i++)
314                                 {
315                                         piRank[i] = 1;
316                                 }
317
318                                 poResult = new types::Polynom(_poSource->getAs<types::Polynom>()->getVariableName(), poDest->getRows(), poDest->getCols(),  piRank);
319
320                                 double *pR = poDest->getReal();
321                                 double *pI = poDest->getImg();
322                                 for(int i = 0 ; i < poDest->getSize() ; i++)
323                                 {
324                                         types::Double *pdbl = NULL;
325                                         if(poDest->isComplex())
326                                         {
327                                                 pdbl = new types::Double(pR[i], pI[i]);
328                                         }
329                                         else
330                                         {
331                                                 pdbl = new types::Double(pR[i]);
332                                         }
333
334                                         poResult->getAs<types::Polynom>()->setCoef(i, pdbl);
335                                         delete pdbl;
336                                 }
337
338                                 poResult->getAs<types::Polynom>()->setCoef(iCurRow, iCurCol, _poSource->getAs<types::Polynom>()->get(0)->getCoef());
339                         }
340                         break;
341                 case types::GenericType::RealPoly :
342                         if(TypeSource == types::GenericType::RealDouble)
343                         {
344                                 //Add Source like coef of the new element
345                                 types::SinglePoly* pPolyOut     = poResult->getAs<types::Polynom>()->get(iCurRow, iCurCol);
346
347                                 pPolyOut->setRank(1);
348                 pPolyOut->setCoef(_poSource->getAs<types::Double>());
349                         }
350                         break;
351                 default:
352                         break;
353                 }
354                 return poResult;
355         }
356         else
357         {//Just add the new value in the current item
358                 switch(TypeDest)
359                 {
360                 case types::GenericType::RealDouble :
361                 {
362             types::Double* pDblSource = _poSource->getAs<types::Double>();
363                         poResult->getAs<types::Double>()->append(iCurRow, iCurCol, pDblSource);
364                         *_piRows = pDblSource->getRows();
365                         *_piCols = pDblSource->getCols();
366                         break;
367                         }
368                 case types::GenericType::RealPoly :
369                         poResult->getAs<types::Polynom>()->append(iCurRow, iCurCol, _poSource->getAs<types::Polynom>());
370                         *_piRows = _poSource->getAsGenericType()->getRows();
371                         *_piCols = _poSource->getAsGenericType()->getCols();
372                         break;
373                 case types::GenericType::RealBool:
374                         poResult->getAs<types::Bool>()->append(iCurRow, iCurCol, _poSource->getAs<types::Bool>());
375                         *_piRows = _poSource->getAsGenericType()->getRows();
376                         *_piCols = _poSource->getAsGenericType()->getCols();
377                         break;
378                 case types::GenericType::RealInt8 :
379                         poResult->getAs<types::Int8>()->append(iCurRow, iCurCol, _poSource->getAs<types::Int8>());
380                         *_piRows = _poSource->getAsGenericType()->getRows();
381                         *_piCols = _poSource->getAsGenericType()->getCols();
382                         break;
383                 case types::GenericType::RealUInt8 :
384                         poResult->getAs<types::UInt8>()->append(iCurRow, iCurCol, _poSource->getAs<types::UInt8>());
385                         *_piRows = _poSource->getAsGenericType()->getRows();
386                         *_piCols = _poSource->getAsGenericType()->getCols();
387                         break;
388                 case types::GenericType::RealInt16 :
389                         poResult->getAs<types::Int16>()->append(iCurRow, iCurCol, _poSource->getAs<types::Int16>());
390                         *_piRows = _poSource->getAsGenericType()->getRows();
391                         *_piCols = _poSource->getAsGenericType()->getCols();
392                         break;
393                 case types::GenericType::RealUInt16 :
394                         poResult->getAs<types::UInt16>()->append(iCurRow, iCurCol, _poSource->getAs<types::UInt16>());
395                         *_piRows = _poSource->getAsGenericType()->getRows();
396                         *_piCols = _poSource->getAsGenericType()->getCols();
397                         break;
398                 case types::GenericType::RealInt32 :
399                         poResult->getAs<types::Int32>()->append(iCurRow, iCurCol, _poSource->getAs<types::Int32>());
400                         *_piRows = _poSource->getAsGenericType()->getRows();
401                         *_piCols = _poSource->getAsGenericType()->getCols();
402                         break;
403                 case types::GenericType::RealUInt32 :
404                         poResult->getAs<types::UInt32>()->append(iCurRow, iCurCol, _poSource->getAs<types::UInt32>());
405                         *_piRows = _poSource->getAsGenericType()->getRows();
406                         *_piCols = _poSource->getAsGenericType()->getCols();
407                         break;
408                 case types::GenericType::RealInt64 :
409                         poResult->getAs<types::Int64>()->append(iCurRow, iCurCol, _poSource->getAs<types::Int64>());
410                         *_piRows = _poSource->getAsGenericType()->getRows();
411                         *_piCols = _poSource->getAsGenericType()->getCols();
412                         break;
413                 case types::GenericType::RealUInt64 :
414                         poResult->getAs<types::UInt64>()->append(iCurRow, iCurCol, _poSource->getAs<types::UInt64>());
415                         *_piRows = _poSource->getAsGenericType()->getRows();
416                         *_piCols = _poSource->getAsGenericType()->getCols();
417                         break;
418                 case types::GenericType::RealString :
419             poResult->getAs<types::String>()->append(iCurRow, iCurCol, _poSource->getAs<types::String>());
420                         *_piRows = _poSource->getAsGenericType()->getRows();
421                         *_piCols = _poSource->getAsGenericType()->getCols();
422                         break;
423                 case types::GenericType::RealImplicitList :
424                         {
425                                 if(_poSource->getAsImplicitList()->getStartType() == types::InternalType::RealPoly)
426                                 {
427                                         poResult->getAsImplicitList()->setStart(_poSource->getAsImplicitList()->getStart());
428                                 }
429                                 else
430                                 {
431                                         poResult->getAsImplicitList()->setStart(_poSource->getAsImplicitList()->getStart());
432                                 }
433
434                                 if(_poSource->getAsImplicitList()->getStepType() == types::InternalType::RealPoly)
435                                 {
436                                         poResult->getAsImplicitList()->setStep(_poSource->getAsImplicitList()->getStep());
437                                 }
438                                 else
439                                 {
440                                         poResult->getAsImplicitList()->setStep(_poSource->getAsImplicitList()->getStep());
441                                 }
442
443                                 if(_poSource->getAsImplicitList()->getEndType() == types::InternalType::RealPoly)
444                                 {
445                                         poResult->getAsImplicitList()->setEnd(_poSource->getAsImplicitList()->getEnd());
446                                 }
447                                 else
448                                 {
449                                         poResult->getAsImplicitList()->setEnd(_poSource->getAsImplicitList()->getEnd());
450                                 }
451                                 break;
452                         }
453                 default:
454                         break;
455                 }
456                 return poResult;
457         }
458         return NULL;
459 }
460
461 const std::wstring* getStructNameFromExp(const Exp* _pExp)
462 {
463     const FieldExp* pField =  dynamic_cast<const FieldExp*>(_pExp);
464     const SimpleVar* pVar =  dynamic_cast<const SimpleVar*>(_pExp);
465     const CallExp* pCall =  dynamic_cast<const CallExp*>(_pExp);
466
467     if(pField)
468     {
469         return getStructNameFromExp(pField->head_get());
470     }
471     else if(pVar)
472     {
473         return &(pVar->name_get().name_get());
474     }
475     else if(pCall)
476     {
477         return getStructNameFromExp(&(pCall->name_get()));
478     }
479     // FIXME
480     return NULL;
481 }
482
483 types::Struct* getStructFromExp(const Exp* _pExp)
484 {
485     const FieldExp* pField =  dynamic_cast<const FieldExp*>(_pExp);
486     const SimpleVar* pVar =  dynamic_cast<const SimpleVar*>(_pExp);
487     const CallExp* pCall =  dynamic_cast<const CallExp*>(_pExp);
488
489     if(pField)
490     {
491         const SimpleVar* pTail = dynamic_cast<const SimpleVar*>(pField->tail_get());
492         if(pTail == NULL)
493         {
494             std::cout << "Houston ..." << std::endl;
495         }
496
497         types::Struct *pStr        = getStructFromExp(pField->head_get());
498
499         pStr->add(pTail->name_get().name_get());
500         types::InternalType* pIT = pStr->get(pTail->name_get().name_get());
501         if(pIT == NULL)
502         {
503             types::Struct* pStruct = new types::Struct();
504             pStr->add(pTail->name_get().name_get(), pStruct);
505             pIT = pStruct;
506         }
507         return pIT->getAsStruct();
508     }
509     else if(pVar)
510     {
511         types::Struct *pStr = NULL;
512         types::InternalType *pIT = symbol::Context::getInstance()->get(pVar->name_get());
513         if(pIT == NULL)
514         {
515             //create new list variable
516             pStr = new types::Struct();
517             //Add variable to scope
518             symbol::Context::getInstance()->put(pVar->name_get(), *pStr);
519         }
520         else if(pIT->isStruct() == false)
521         {
522             return NULL;
523         }
524         else
525         {
526             pStr = pIT->getAsStruct();
527         }
528
529         return pStr;
530     }
531     else if(pCall)
532     {
533         // FIXME
534         return NULL;
535     }
536     // FIXME
537     return NULL;
538 }
539
540 void callOnPrompt(void)
541 {
542     types::InternalType* pOnPrompt = NULL;
543     pOnPrompt = symbol::Context::getInstance()->get(symbol::Symbol(L"%onprompt"));
544     if(pOnPrompt != NULL && pOnPrompt->isCallable())
545     {
546         types::typed_list in;
547         types::typed_list out;
548         ExecVisitor execCall;
549         pOnPrompt->getAs<types::Callable>()->call(in, 1, out, &execCall);
550     }
551 }