* Bug 16122 fixed: now concat polynomials with <> var raises an error
[scilab.git] / scilab / modules / ast / src / cpp / ast / 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  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 #include <string>
17 #include <numeric>
18 #include <iostream>
19 #include <fstream>
20 #include "visitor_common.hxx"
21 #include "exp.hxx"
22 #include "fieldexp.hxx"
23 #include "simplevar.hxx"
24 #include "callexp.hxx"
25 #include "struct.hxx"
26 #include "context.hxx"
27 #include "execvisitor.hxx"
28 #include "serializervisitor.hxx"
29 #include "deserializervisitor.hxx"
30 #include "localization.hxx"
31 #include "user.hxx"
32
33 #include "alltypes.hxx"
34
35 extern "C"
36 {
37 #include "storeCommand.h"
38 }
39
40 size_t ast::Ast::globalNodeNumber = 0;
41
42 /*
43  * Generate destination variable from _poSource type and size parameters
44  */
45 static types::InternalType* allocDest(types::InternalType* _poSource, int _iRows, int _iCols)
46 {
47     types::InternalType* poResult = NULL;
48     switch (_poSource->getType())
49     {
50         case types::InternalType::ScilabDouble:
51             poResult = new types::Double(_iRows, _iCols, false);
52             break;
53         case types::InternalType::ScilabBool:
54             poResult = new types::Bool(_iRows, _iCols);
55             break;
56         case types::InternalType::ScilabInt8:
57             poResult = new types::Int8(_iRows, _iCols);
58             break;
59         case types::InternalType::ScilabUInt8:
60             poResult = new types::UInt8(_iRows, _iCols);
61             break;
62         case types::InternalType::ScilabInt16:
63             poResult = new types::Int16(_iRows, _iCols);
64             break;
65         case types::InternalType::ScilabUInt16:
66             poResult = new types::UInt16(_iRows, _iCols);
67             break;
68         case types::InternalType::ScilabInt32:
69             poResult = new types::Int32(_iRows, _iCols);
70             break;
71         case types::InternalType::ScilabUInt32:
72             poResult = new types::UInt32(_iRows, _iCols);
73             break;
74         case types::InternalType::ScilabInt64:
75             poResult = new types::Int64(_iRows, _iCols);
76             break;
77         case types::InternalType::ScilabUInt64:
78             poResult = new types::UInt64(_iRows, _iCols);
79             break;
80         case types::InternalType::ScilabString:
81             poResult = new types::String(_iRows, _iCols);
82             break;
83         case types::InternalType::ScilabCell:
84             poResult = new types::Cell(_iRows, _iCols);
85             break;
86         case types::InternalType::ScilabPolynom:
87         {
88             int* piRank = new int[_iRows * _iCols];
89             memset(piRank, 0x00, _iRows * _iCols * sizeof(int));
90             poResult = new types::Polynom(_poSource->getAs<types::Polynom>()->getVariableName(), _iRows, _iCols, piRank);
91             delete[] piRank;
92             break;
93         }
94         case types::InternalType::ScilabImplicitList:
95             poResult = new types::ImplicitList();
96             break;
97         default:
98             // FIXME : What should we do here ??
99             break;
100     }
101     return poResult;
102 }
103
104 types::InternalType* AddElementToVariableFromCol(types::InternalType* _poDest, types::InternalType* _poSource, int _iRows, int _iCols, int *_piCols)
105 {
106     types::InternalType *poResult = NULL;
107     types::InternalType::ScilabType TypeSource = _poSource->getType();
108     types::InternalType::ScilabType TypeDest = types::InternalType::ScilabInternal;
109
110     if (_poDest == NULL)
111     {
112         //First call, alloc _poSource
113         poResult = allocDest(_poSource, _iRows, _iCols);
114         TypeDest = TypeSource;
115     }
116     else
117     {
118         TypeDest = _poDest->getType();
119         poResult = _poDest;
120     }
121
122     if (TypeDest != TypeSource)
123     {
124         //check if source type is compatible with dest type
125     }
126     else
127     {
128         switch (TypeDest)
129         {
130             case types::InternalType::ScilabDouble:
131                 if (poResult->getAs<types::Double>()->isComplex() == false && _poSource->getAs<types::Double>()->isComplex() == true)
132                 {
133                     poResult->getAs<types::Double>()->setComplex(true);
134                 }
135
136                 poResult->getAs<types::Double>()->fillFromCol(*_piCols, _poSource->getAs<types::Double>());
137                 *_piCols += _poSource->getAs<types::Double>()->getCols();
138
139                 break;
140             default:
141                 break;
142         }
143         return poResult;
144     }
145     return NULL;
146 }
147
148 types::InternalType* AddElementToVariableFromRow(types::InternalType* _poDest, types::InternalType* _poSource, int _iRows, int _iCols, int *_piRows)
149 {
150     types::InternalType *poResult = NULL;
151     types::InternalType::ScilabType TypeSource = _poSource->getType();
152     types::InternalType::ScilabType TypeDest = types::InternalType::ScilabInternal;
153
154     if (_poDest == NULL)
155     {
156         //First call, alloc _poSource
157         poResult = allocDest(_poSource, _iRows, _iCols);
158         TypeDest = TypeSource;
159     }
160     else
161     {
162         TypeDest = _poDest->getType();
163         poResult = _poDest;
164     }
165
166
167     if (TypeDest != TypeSource)
168     {
169         //check if source type is compatible with dest type
170     }
171     else
172     {
173         switch (TypeDest)
174         {
175             case types::InternalType::ScilabDouble:
176                 if (poResult->getAs<types::Double>()->isComplex() == false && _poSource->getAs<types::Double>()->isComplex() == true)
177                 {
178                     poResult->getAs<types::Double>()->setComplex(true);
179                 }
180
181                 poResult->getAs<types::Double>()->fillFromRow(*_piRows, _poSource->getAs<types::Double>());
182                 *_piRows += _poSource->getAs<types::Double>()->getRows();
183
184                 break;
185             default:
186                 break;
187         }
188         return poResult;
189     }
190     return NULL;
191 }
192
193
194 /*
195 _iRows : Position if _poDest allready initialized else size of the matrix
196 _iCols : Position if _poDest allready initialized else size of the matrix
197 */
198 types::InternalType* AddElementToVariable(types::InternalType* _poDest, types::InternalType* _poSource, int _iRows, int _iCols)
199 {
200     types::InternalType *poResult = NULL;
201     bool isNew = true;
202     types::InternalType::ScilabType TypeSource = _poSource->getType();
203     types::InternalType::ScilabType TypeDest = types::InternalType::ScilabInternal;
204     int iCurRow = _iRows;
205     int iCurCol = _iCols;
206
207     if (_poDest == NULL)
208     {
209         switch (TypeSource)
210         {
211             case types::InternalType::ScilabDouble:
212                 poResult = new types::Double(_iRows, _iCols);
213                 break;
214             case types::InternalType::ScilabBool:
215                 poResult = new types::Bool(_iRows, _iCols);
216                 break;
217             case types::InternalType::ScilabInt8:
218                 poResult = new types::Int8(_iRows, _iCols);
219                 break;
220             case types::InternalType::ScilabUInt8:
221                 poResult = new types::UInt8(_iRows, _iCols);
222                 break;
223             case types::InternalType::ScilabInt16:
224                 poResult = new types::Int16(_iRows, _iCols);
225                 break;
226             case types::InternalType::ScilabUInt16:
227                 poResult = new types::UInt16(_iRows, _iCols);
228                 break;
229             case types::InternalType::ScilabInt32:
230                 poResult = new types::Int32(_iRows, _iCols);
231                 break;
232             case types::InternalType::ScilabUInt32:
233                 poResult = new types::UInt32(_iRows, _iCols);
234                 break;
235             case types::InternalType::ScilabInt64:
236                 poResult = new types::Int64(_iRows, _iCols);
237                 break;
238             case types::InternalType::ScilabUInt64:
239                 poResult = new types::UInt64(_iRows, _iCols);
240                 break;
241             case types::InternalType::ScilabString:
242                 poResult = new types::String(_iRows, _iCols);
243                 break;
244             case types::InternalType::ScilabSparse:
245                 poResult = new types::Sparse(_iRows, _iCols);
246                 break;
247             case types::InternalType::ScilabSparseBool:
248                 poResult = new types::SparseBool(_iRows, _iCols);
249                 break;
250             case types::InternalType::ScilabPolynom:
251             {
252                 int* piRank = new int[_iRows * _iCols];
253                 memset(piRank, 0x00, _iRows * _iCols * sizeof(int));
254                 poResult = new types::Polynom(_poSource->getAs<types::Polynom>()->getVariableName(), _iRows, _iCols, piRank);
255                 delete[] piRank;
256                 break;
257             }
258             case types::InternalType::ScilabImplicitList:
259                 poResult = new types::ImplicitList();
260                 break;
261             case types::InternalType::ScilabHandle:
262                 poResult = new types::GraphicHandle(_iRows, _iCols);
263                 break;
264             case types::InternalType::ScilabCell:
265                 poResult = new types::Cell(_iRows, _iCols);
266                 break;
267             default:
268                 // FIXME What should we do here ...
269                 break;
270         }
271         iCurCol = 0;
272         iCurRow = 0;
273         TypeDest = TypeSource;
274     }
275     else
276     {
277         TypeDest = _poDest->getType();
278         poResult = _poDest;
279         isNew = false;
280     }
281
282
283     if (TypeDest != TypeSource)
284     {
285         //check if source type is compatible with dest type
286         switch (TypeDest)
287         {
288             case types::InternalType::ScilabDouble:
289                 if (TypeSource == types::InternalType::ScilabPolynom)
290                 {
291                     types::Double *poDest = _poDest->getAs<types::Double>();
292                     types::Polynom* pPSource = _poSource->getAs<types::Polynom>();
293
294                     //Convert Dest to ScilabPolynom
295                     int iSize = poDest->getSize();
296                     int *piRank = new int[iSize];
297                     memset(piRank, 0x00, iSize * sizeof(int));
298                     if (isNew && poResult)
299                     {
300                         poResult->killMe();
301                     }
302                     poResult = new types::Polynom(pPSource->getVariableName(), poDest->getRows(), poDest->getCols(), piRank);
303                     delete[] piRank;
304
305                     types::Polynom* pPResult = poResult->getAs<types::Polynom>();
306                     pPResult->setComplex(poDest->isComplex());
307
308                     double *pR = poDest->getReal();
309                     types::SinglePoly** pSP = pPResult->get();
310
311                     if (poDest->isComplex())
312                     {
313                         double *pI = poDest->getImg();
314                         for (int i = 0; i < iSize; i++)
315                         {
316                             pSP[i]->set(0, pR[i]);
317                             pSP[i]->setImg(0, pI[i]);
318                         }
319                     }
320                     else
321                     {
322                         for (int i = 0; i < iSize; i++)
323                         {
324                             pSP[i]->set(0, pR[i]);
325                         }
326                     }
327
328                     for (int i = 0; i < pPSource->getRows(); i++)
329                     {
330                         for (int j = 0; j < pPSource->getCols(); j++)
331                         {
332                             pPResult->set(iCurRow + i, iCurCol + j, pPSource->get(i, j));
333                         }
334                     }
335
336                     return poResult;
337                 }
338                 break;
339             case types::InternalType::ScilabPolynom:
340                 if (TypeSource == types::InternalType::ScilabDouble)
341                 {
342                     //Add Source like coef of the new element
343                     types::Double* pD = _poSource->getAs<types::Double>();
344                     types::Polynom* pPolyOut = poResult->getAs<types::Polynom>();
345
346                     if (pD->isComplex())
347                     {
348                         pPolyOut->setComplex(true);
349                         for (int i = 0; i < pD->getRows(); i++)
350                         {
351                             for (int j = 0; j < pD->getCols(); j++)
352                             {
353                                 types::SinglePoly* pSPOut = pPolyOut->get(iCurRow + i, iCurCol + j);
354
355                                 pSPOut->setRank(0);
356                                 double pDblR = pD->get(i, j);
357                                 double pDblI = pD->getImg(i, j);
358                                 pSPOut->setCoef(&pDblR, &pDblI);
359                             }
360                         }
361                     }
362                     else
363                     {
364                         for (int i = 0; i < pD->getRows(); i++)
365                         {
366                             for (int j = 0; j < pD->getCols(); j++)
367                             {
368                                 types::SinglePoly* pSPOut = pPolyOut->get(iCurRow + i, iCurCol + j);
369
370                                 pSPOut->setRank(0);
371                                 double pDbl = pD->get(i, j);
372                                 pSPOut->setCoef(&pDbl, NULL);
373                             }
374                         }
375                     }
376
377                     return poResult;
378                 }
379                 break;
380             case types::InternalType::ScilabSparse:
381                 if (TypeSource == types::InternalType::ScilabDouble)
382                 {
383                     types::Double* poSource = _poSource->getAs<types::Double>();
384                     types::Sparse* spResult = poResult->getAs<types::Sparse>();
385
386                     // Set complex the result if one of inputs is complex
387                     if (poSource->isComplex())
388                     {
389                         if (spResult->isComplex() == false)
390                         {
391                             spResult->toComplex();
392                         }
393                     }
394
395                     // Add poSource at the end of spResult
396                     if (spResult->isComplex())
397                     {
398                         if (poSource->isComplex())
399                         {
400                             for (int i = 0; i < poSource->getRows(); i++)
401                             {
402                                 for (int j = 0; j < poSource->getCols(); j++)
403                                 {
404                                     double dbl = poSource->get(i, j);
405                                     double dblImg = poSource->getImg(i, j);
406                                     if (dbl != 0 || dblImg != 0)
407                                     {
408                                         spResult->set(i + iCurRow, j + iCurCol, std::complex<double>(dbl, dblImg));
409                                     }
410                                 }
411                             }
412                         }
413                         else
414                         {
415                             for (int i = 0; i < poSource->getRows(); i++)
416                             {
417                                 for (int j = 0; j < poSource->getCols(); j++)
418                                 {
419                                     double dbl = poSource->get(i, j);
420                                     if (dbl != 0)
421                                     {
422                                         spResult->set(i + iCurRow, j + iCurCol, std::complex<double>(dbl, 0));
423                                     }
424                                 }
425                             }
426                         }
427                     }
428                     else
429                     {
430                         for (int i = 0; i < poSource->getRows(); i++)
431                         {
432                             for (int j = 0; j < poSource->getCols(); j++)
433                             {
434                                 double dbl = poSource->get(i, j);
435                                 if (dbl != 0)
436                                 {
437                                     spResult->set(i + iCurRow, j + iCurCol, dbl);
438                                 }
439                             }
440                         }
441                     }
442
443                     return poResult;
444                 }
445                 break;
446             case types::InternalType::ScilabSparseBool:
447                 if (TypeSource == types::InternalType::ScilabBool)
448                 {
449                     types::Bool* poSource = _poSource->getAs<types::Bool>();
450                     types::SparseBool* spResult = poResult->getAs<types::SparseBool>();
451
452                     // Add poSource at the end of spResult
453                     for (int i = 0; i < poSource->getRows(); i++)
454                     {
455                         for (int j = 0; j < poSource->getCols(); j++)
456                         {
457                             bool bValue = poSource->get(i, j) != 0;
458                             if (bValue)
459                             {
460                                 spResult->set(i + iCurRow, j + iCurCol, true);
461                             }
462                         }
463                     }
464
465                     return poResult;
466                 }
467                 break;
468             default:
469                 break;
470         }
471
472         if (poResult && isNew)
473         {
474             poResult->killMe();
475         }
476
477         // call overload
478         return NULL;
479     }
480     else
481     {
482         //Just add the new value in the current item
483         switch (TypeDest)
484         {
485             case types::InternalType::ScilabDouble:
486                 poResult->getAs<types::Double>()->append(iCurRow, iCurCol, _poSource);
487                 break;
488             case types::InternalType::ScilabPolynom:
489                 if (poResult->getAs<types::Polynom>()->getVariableName() !=  _poSource->getAs<types::Polynom>()->getVariableName())
490                 {
491                     // call overload
492                     return NULL;
493                 }
494                 poResult->getAs<types::Polynom>()->append(iCurRow, iCurCol, _poSource);
495                 break;
496             case types::InternalType::ScilabBool:
497                 poResult->getAs<types::Bool>()->append(iCurRow, iCurCol, _poSource);
498                 break;
499             case types::InternalType::ScilabInt8:
500                 poResult->getAs<types::Int8>()->append(iCurRow, iCurCol, _poSource);
501                 break;
502             case types::InternalType::ScilabUInt8:
503                 poResult->getAs<types::UInt8>()->append(iCurRow, iCurCol, _poSource);
504                 break;
505             case types::InternalType::ScilabInt16:
506                 poResult->getAs<types::Int16>()->append(iCurRow, iCurCol, _poSource);
507                 break;
508             case types::InternalType::ScilabUInt16:
509                 poResult->getAs<types::UInt16>()->append(iCurRow, iCurCol, _poSource);
510                 break;
511             case types::InternalType::ScilabInt32:
512                 poResult->getAs<types::Int32>()->append(iCurRow, iCurCol, _poSource);
513                 break;
514             case types::InternalType::ScilabUInt32:
515                 poResult->getAs<types::UInt32>()->append(iCurRow, iCurCol, _poSource);
516                 break;
517             case types::InternalType::ScilabInt64:
518                 poResult->getAs<types::Int64>()->append(iCurRow, iCurCol, _poSource);
519                 break;
520             case types::InternalType::ScilabUInt64:
521                 poResult->getAs<types::UInt64>()->append(iCurRow, iCurCol, _poSource);
522                 break;
523             case types::InternalType::ScilabSparse:
524                 poResult->getAs<types::Sparse>()->append(iCurRow, iCurCol, _poSource->getAs<types::Sparse>());
525                 break;
526             case types::InternalType::ScilabSparseBool:
527                 poResult->getAs<types::SparseBool>()->append(iCurRow, iCurCol, _poSource->getAs<types::SparseBool>());
528                 break;
529             case types::InternalType::ScilabString:
530                 poResult->getAs<types::String>()->append(iCurRow, iCurCol, _poSource);
531                 break;
532             case types::InternalType::ScilabCell:
533                 poResult->getAs<types::Cell>()->append(iCurRow, iCurCol, _poSource);
534                 break;
535             case types::InternalType::ScilabImplicitList:
536             {
537                 types::ImplicitList* pIL = _poSource->getAs<types::ImplicitList>();
538                 types::ImplicitList* pOL = poResult->getAs<types::ImplicitList>();
539                 pOL->setStart(pIL->getStart());
540                 pOL->setStep(pIL->getStep());
541                 pOL->setEnd(pIL->getEnd());
542                 break;
543             }
544             case types::InternalType::ScilabHandle:
545                 poResult->getAs<types::GraphicHandle>()->append(iCurRow, iCurCol, _poSource);
546                 break;
547             default:
548             {
549                 if (poResult && isNew)
550                 {
551                     poResult->killMe();
552                 }
553
554                 // call overload
555                 return NULL;
556             }
557         }
558         return poResult;
559     }
560 }
561
562 const std::wstring* getStructNameFromExp(const ast::Exp* _pExp)
563 {
564     const ast::FieldExp* pField = dynamic_cast<const ast::FieldExp*>(_pExp);
565     const ast::SimpleVar* pVar = dynamic_cast<const ast::SimpleVar*>(_pExp);
566     const ast::CallExp* pCall = dynamic_cast<const ast::CallExp*>(_pExp);
567
568     if (pField)
569     {
570         return getStructNameFromExp(pField->getHead());
571     }
572     else if (pVar)
573     {
574         return &(pVar->getSymbol().getName());
575     }
576     else if (pCall)
577     {
578         return getStructNameFromExp(&(pCall->getName()));
579     }
580     else
581     {
582         std::wostringstream os;
583         os << _W("Unknown expression");
584         //os << ((Location)e.getRightExp().getLocation()).getLocationString() << std::endl;
585         throw ast::InternalError(os.str(), 999, _pExp->getLocation());
586     }
587     return NULL;
588 }
589
590 /*** overload insertion                 ||         extraction       ***/
591 //%x_i_x(i1, i2, ..., in, source, dest) || %x_e(i1, i2, ..., in, source, dest)
592 //i1, ..., in : indexes
593 //dest : variable where insert data     || NULL
594 //source : data to insert               || extract indexes from source
595 types::InternalType* callOverload(const ast::Exp& e, const std::wstring& _strType, types::typed_list* _pArgs, types::InternalType* _source, types::InternalType* _dest)
596 {
597     types::Function::ReturnValue ret = types::Function::Error;
598     types::InternalType* pITOut = NULL;
599     types::typed_list in;
600     types::typed_list out;
601
602     std::wstring function_name;
603     function_name = L"%" + _source->getShortTypeStr() + L"_" + _strType;
604
605     for (int i = 0; i < (int)_pArgs->size(); i++)
606     {
607         (*_pArgs)[i]->IncreaseRef();
608         in.push_back((*_pArgs)[i]);
609     }
610
611     _source->IncreaseRef();
612     in.push_back(_source);
613
614     if (_dest)
615     {
616         _dest->IncreaseRef();
617         in.push_back(_dest);
618
619         function_name += L"_" + _dest->getShortTypeStr();
620     }
621
622     types::InternalType* pFunc = symbol::Context::getInstance()->get(symbol::Symbol(function_name));
623     if (pFunc == NULL &&
624             (_source->getShortTypeStr().size() > 8 || (_dest && _dest->getShortTypeStr().size() > 8)))
625     {
626         if (_source->getShortTypeStr().size() > 8)
627         {
628             function_name = L"%" + _source->getShortTypeStr().substr(0, 8) + L"_" + _strType;
629         }
630         else if (_dest)
631         {
632             function_name = L"%" + _source->getShortTypeStr() + L"_" + _strType;
633         }
634
635         if (_dest && _dest->getShortTypeStr().size() > 8)
636         {
637             function_name += L"_" + _dest->getShortTypeStr().substr(0, 8);
638         }
639
640         pFunc = symbol::Context::getInstance()->get(symbol::Symbol(function_name));
641     }
642
643     // if %type_6 doesn't exist, call %l_6
644     if (_dest == NULL && pFunc == NULL)
645     {
646         function_name = L"%l_" + _strType;
647     }
648
649     // For insertion in TList, call normal insertion if overload doesn't exits
650     if ((_dest  && _dest->isTList() && pFunc == NULL) == false || _source->isListDelete())
651     {
652         try
653         {
654             ret = Overload::call(function_name, in, 1, out);
655         }
656         catch (const ast::InternalError& error)
657         {
658             // unprotect variables
659             for (int i = 0; i < (int)_pArgs->size(); i++)
660             {
661                 (*_pArgs)[i]->DecreaseRef();
662             }
663
664             _source->DecreaseRef();
665             if (_dest)
666             {
667                 _dest->DecreaseRef();
668             }
669
670             throw error;
671         }
672
673         // unprotect variables
674         for (int i = 0; i < (int)_pArgs->size(); i++)
675         {
676             (*_pArgs)[i]->DecreaseRef();
677         }
678
679         _source->DecreaseRef();
680         if (_dest)
681         {
682             _dest->DecreaseRef();
683         }
684
685         if (ret == types::Function::Error)
686         {
687             //manage error
688             std::wostringstream os;
689             os << _W("Error in overload function: ") << function_name << std::endl;
690             throw ast::InternalError(os.str(), 999, e.getLocation());
691         }
692     }
693
694     if (out.size() == 1)
695     {
696         pITOut = out[0];
697     }
698     else if (out.size() > 1)
699     {
700         types::List* pListOut = new types::List();
701         for (int i = 0; i < (int)out.size(); i++)
702         {
703             pListOut->append(out[i]);
704         }
705
706         pITOut = pListOut;
707     }
708
709     return pITOut;
710 }
711
712
713 bool getFieldsFromExp(ast::Exp* _pExp, std::list<ExpHistory*>& fields)
714 {
715     ast::FieldExp* pField = dynamic_cast<ast::FieldExp*>(_pExp);
716     ast::SimpleVar* pVar = dynamic_cast<ast::SimpleVar*>(_pExp);
717     ast::CallExp* pCall = dynamic_cast<ast::CallExp*>(_pExp);
718     ast::CellCallExp* pCell = dynamic_cast<ast::CellCallExp*>(_pExp);
719
720     if (pField)
721     {
722         if (getFieldsFromExp(pField->getHead(), fields))
723         {
724             return getFieldsFromExp(pField->getTail(), fields);
725         }
726
727         return false;
728     }
729     else if (pVar)
730     {
731         if (fields.empty())
732         {
733             fields.push_back(new ExpHistory(NULL, pVar));
734         }
735         else
736         {
737             ExpHistory * pEHParent = fields.back();
738             ExpHistory * pEH = new ExpHistory(pEHParent, pVar);
739             pEH->setLevel(pEHParent->getLevel() + 1);
740             fields.push_back(pEH);
741         }
742
743         return true;
744     }
745     else if (pCall)
746     {
747         bool bArgList = false;
748         types::List* pList = NULL;
749         int iListIncr = 0;
750         int iListSize = 0;
751
752         ast::ExecVisitor execMe;
753         ast::exps_t args = pCall->getArgs();
754         types::typed_list* pCurrentArgs = execMe.GetArgumentList(args);
755
756         if (getFieldsFromExp(&pCall->getName(), fields) == false)
757         {
758             return false;
759         }
760
761         // used to manage insertion with list in argument
762         // a(list("field", 2)) = 2 as a.field(2)
763         if (pCurrentArgs &&  pCurrentArgs->size() > 0 &&
764                 (*pCurrentArgs)[0]->isList() &&
765                 (*pCurrentArgs)[0]->isTList() == false &&
766                 (*pCurrentArgs)[0]->isMList() == false)
767         {
768             bArgList = true;
769             pList = (*pCurrentArgs)[0]->getAs<types::List>();
770             //pList->IncreaseRef();
771             pCurrentArgs->clear();
772             pCurrentArgs->push_back(pList->get(iListIncr));
773             iListSize = pList->getSize();
774
775         }
776
777         do
778         {
779             if (pCurrentArgs &&
780                     pCurrentArgs->size() == 1 &&
781                     (*pCurrentArgs)[0]->isString() &&
782                     (*pCurrentArgs)[0]->getAs<types::String>()->getSize() == 1)
783             {
784                 // a("b") => a.b or a(x)("b") => a(x).b
785                 ExpHistory * pEHParent = fields.back();
786                 ast::SimpleVar* pFieldVar = new ast::SimpleVar(pCall->getLocation(), symbol::Symbol((*pCurrentArgs)[0]->getAs<types::String>()->get(0)));
787                 ExpHistory * pEH = new ExpHistory(pEHParent, pFieldVar);
788                 pEH->setLevel(pEHParent->getLevel() + 1);
789                 pEH->setExpOwner(true);
790
791                 (*pCurrentArgs)[0]->killMe();
792                 delete pCurrentArgs;
793                 pCurrentArgs = NULL;
794
795                 fields.push_back(pEH);
796             }
797             else if (fields.back()->getArgs())
798             {
799                 // a(x)(y)(z)
800                 ExpHistory * pEHParent = fields.back();
801                 ExpHistory * pEH = new ExpHistory(pEHParent, pCurrentArgs);
802                 pEH->setLevel(pEHParent->getLevel() + 1);
803                 pEH->setArgsOwner(true);
804                 fields.push_back(pEH);
805             }
806             else
807             {
808                 // a(x)
809                 fields.back()->setArgs(pCurrentArgs);
810                 fields.back()->setArgsOwner(true);
811             }
812
813             if (bArgList)
814             {
815                 iListIncr++;
816                 if (iListIncr < iListSize)
817                 {
818                     // create new args for next loop.
819                     pCurrentArgs = new types::typed_list();
820                     pCurrentArgs->push_back(pList->get(iListIncr)->clone());
821                 }
822             }
823         }
824         while (iListIncr < iListSize);
825
826         if (bArgList)
827         {
828             pList->killMe();
829         }
830
831         if (pCell)
832         {
833             // a{x}
834             fields.back()->setCellExp();
835         }
836
837         return true;
838     }
839     else
840     {
841         return false;
842     }
843 }
844
845 types::InternalType* evaluateFields(const ast::Exp* _pExp, std::list<ExpHistory*>& fields, types::InternalType* _pAssignValue)
846 {
847     std::list<ExpHistory*> evalFields;
848     std::list<ExpHistory*> workFields;
849
850     bool bPutInCtx = false;
851     types::InternalType* pITMain = NULL;
852
853     try
854     {
855         //*** get main variable ***//
856         std::list<ExpHistory*>::iterator iterFields = fields.begin();
857         ExpHistory* pFirstField = *iterFields;
858         symbol::Context* ctx = symbol::Context::getInstance();
859
860         if (ctx->isprotected(pFirstField->getExp()->getSymbol()))
861         {
862             std::wostringstream os;
863             os << _W("Redefining permanent variable.\n");
864             throw ast::InternalError(os.str(), 999, _pExp->getLocation());
865         }
866
867         ast::SimpleVar* spMainExp = pFirstField->getExp();
868         pITMain = ctx->getCurrentLevel(spMainExp->getSymbol());
869
870         // looking for a callable
871         if (pITMain == NULL)
872         {
873             pITMain = ctx->get(spMainExp->getSymbol());
874             if (pITMain && pITMain->isCallable() == false)
875             {
876                 pITMain = NULL;
877             }
878         }
879
880         if (pITMain == NULL)
881         {
882             if (pFirstField->isCellExp())
883             {
884                 // a{x}, where "a" doesn't exists
885                 pITMain = new types::Cell(1, 1);
886                 pITMain->IncreaseRef();
887                 bPutInCtx = true;
888             }
889             else if (fields.size() > 1)
890             {
891                 // is a field exp
892                 //"a" does not exist or it is another type, create it with size 1,1 and return it
893                 //create new structure variable
894                 pITMain = new types::Struct(1, 1);
895                 pITMain->IncreaseRef();
896                 bPutInCtx = true;
897             }
898             // else
899             // is a call exp
900             // a(x) = "something" and a does not exist
901             // a will be create in insertionCall
902         }
903         else if (pITMain->getRef() > 1 && pITMain->isHandle() == false)
904         {
905             bPutInCtx = true;
906             pITMain = pITMain->clone();
907             pITMain->IncreaseRef();
908         }
909         else if (pITMain == _pAssignValue)
910         {
911             // clone me before insert me in myself.
912             // ie : a.b = 2; a.b.c.d = a;
913             _pAssignValue = _pAssignValue->clone();
914         }
915
916         iterFields++;
917
918         workFields.push_back(new ExpHistory(NULL,
919                                             pFirstField->getExp(),
920                                             pFirstField->getArgs(),
921                                             pFirstField->getLevel(),
922                                             pFirstField->isCellExp(),
923                                             pITMain));
924
925         //*** evaluate fields ***//
926         while (iterFields != fields.end())
927         {
928             ExpHistory* pEH = workFields.front();
929             evalFields.push_back(pEH);
930             workFields.pop_front();
931
932             types::InternalType* pITCurrent = pEH->getCurrent();
933
934             if (pEH->isCellExp() && pITCurrent->isCell() == false)
935             {
936                 std::wostringstream os;
937                 os << _W("Wrong insertion : use extraction with {} only on a Cell.");
938                 throw ast::InternalError(os.str(), 999, _pExp->getLocation());
939             }
940
941             if (pITCurrent->isStruct())
942             {
943                 types::Struct* pStruct = pITCurrent->getAs<types::Struct>();
944                 // In case where pStruct is in several scilab variable,
945                 // we have to clone it for keep the other variables unchanged.
946                 if (pStruct->getRef() > 1)
947                 {
948                     pStruct = pStruct->clone();
949                     pEH->setCurrent(pStruct);
950                     pEH->setReinsertion();
951                 }
952
953                 std::wstring pwcsFieldname = (*iterFields)->getExpAsString();
954
955                 if (pEH->needResize())
956                 {
957                     if (pEH->getArgsDims() == 1)
958                     {
959                         std::wostringstream os;
960                         os << _W("Invalid index.\n");
961                         throw ast::InternalError(os.str(), 999, _pExp->getLocation());
962                     }
963
964                     // resize current struct
965                     pStruct = pStruct->resize(pEH->getArgsDimsArray(), pEH->getArgsDims());
966                     pEH->setCurrent(pStruct);
967                 }
968
969                 // create field in parent if it not exist
970                 if (pStruct->exists(pwcsFieldname) == false)
971                 {
972                     pStruct = pStruct->addField(pwcsFieldname);
973                     pEH->setCurrent(pStruct);
974                 }
975
976                 if (pEH->getArgs())
977                 {
978                     types::InternalType* pIT = pStruct->extractWithoutClone(pEH->getArgs());
979                     workFields.push_front(new ExpHistory(pEH, pEH->getExp(), NULL, pEH->getLevel(), pEH->isCellExp(), pIT));
980                 }
981                 else
982                 {
983                     // check if the field x is the last field
984                     std::list<ExpHistory*>::iterator iterFieldsNext(iterFields);
985                     ++iterFieldsNext;
986                     if (iterFieldsNext == fields.end() && (*iterFields)->getArgs() == NULL)
987                     {
988                         // create pArg with "x" and set it as argument of "a"
989                         types::typed_list* args = new types::typed_list();
990                         args->push_back(new types::String(pwcsFieldname.c_str()));
991                         pEH->setArgs(args);
992
993                         // a.x where x is the last field
994                         // insert directly in x instead of extract then insert
995                         ExpHistory* pEHNext = new ExpHistory(pEH, (*iterFields)->getExp(), (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), _pAssignValue);
996                         pEHNext->setReinsertion(true);
997                         evalFields.push_back(pEHNext);
998                         if (workFields.empty())
999                         {
1000                             break;
1001                         }
1002                     }
1003                     else
1004                     {
1005                         // Avoid insertion in most of one element.
1006                         if (pStruct->isScalar() == false)
1007                         {
1008                             std::wostringstream os;
1009                             os << _W("Unable to insert multiple item in a Struct.");
1010                             throw ast::InternalError(os.str(), 999, _pExp->getLocation());
1011                         }
1012
1013                         // extract field x and append it to elements for next recursion.
1014                         types::List* pLOut = pStruct->extractFieldWithoutClone(pwcsFieldname);
1015
1016                         // pStruct must be scalar because we cant insert most of one element in the same insertion
1017                         types::InternalType* pIT = pLOut->get(0);
1018                         if (pIT->getRef() > 2) //One for my own ref + 1 for "extractFieldWithoutClone" artificial ref
1019                         {
1020                             // clone element before modify it.
1021                             //pIT->DecreaseRef();
1022                             pIT = pIT->clone();
1023                             pStruct->get(0)->set(pwcsFieldname, pIT);
1024                         }
1025
1026                         ExpHistory* pEHChield = new ExpHistory(pEH,
1027                                                                (*iterFields)->getExp(),
1028                                                                (*iterFields)->getArgs(),
1029                                                                (*iterFields)->getLevel(),
1030                                                                (*iterFields)->isCellExp(),
1031                                                                pIT);
1032
1033                         pEHChield->setWhereReinsert(0);
1034                         workFields.push_back(pEHChield);
1035
1036                         pLOut->killMe();
1037                     }
1038                 }
1039             }
1040             else if (pITCurrent->isTList() || pITCurrent->isMList())
1041             {
1042                 types::TList* pTL = pITCurrent->getAs<types::TList>();
1043                 types::typed_list* pArgs = pEH->getArgs();
1044                 if (pArgs)
1045                 {
1046                     if (pArgs->size() > 1 || pITCurrent->isMList())
1047                     {
1048                         // call overload
1049                         types::InternalType* pExtract = callOverload(*pEH->getExp(), L"6", pArgs, pTL, NULL);
1050                         if ((*iterFields)->getExp() == NULL)
1051                         {
1052                             // a(x)(y)
1053                             // extract a(x) and push_BACK to extract y
1054                             workFields.push_back(new ExpHistory(pEH, NULL, (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), pExtract));
1055                             workFields.back()->setReinsertion();
1056                         }
1057                         else
1058                         {
1059                             // a(x).b
1060                             // extract a(x) and push_FRONT to extract b
1061                             workFields.push_front(new ExpHistory(pEH, pEH->getExp(), NULL, pEH->getLevel(), pEH->isCellExp(), pExtract));
1062                             workFields.front()->setReinsertion();
1063                         }
1064                     }
1065                     else
1066                     {
1067                         // resize TList
1068                         int iNewSize = pEH->getSizeFromArgs();
1069                         if (pTL->getSize() < iNewSize)
1070                         {
1071                             pTL = pTL->set(iNewSize - 1, new types::Void());
1072                             pEH->setCurrent(pTL);
1073                         }
1074
1075                         // update pArgs variables with new argument computed in getSizeFromArgs
1076                         pArgs = pEH->getArgs();
1077
1078                         types::InternalType* pIT = pTL->extract(pArgs);
1079                         types::List* pList = pIT->getAs<types::List>();
1080
1081                         if (pList->getSize() > 1)
1082                         {
1083                             pList->killMe();
1084                             std::wostringstream os;
1085                             os << _W("Unable to insert multiple item in a List.");
1086                             throw ast::InternalError(os.str(), 999, _pExp->getLocation());
1087                         }
1088
1089                         double* pdblArgs = (*pArgs)[0]->getAs<types::Double>()->get();
1090                         if ((*iterFields)->getExp() == NULL)
1091                         {
1092                             // a(x)(y)
1093                             // extract a(x) and push_BACK to extract y
1094                             ExpHistory* pEHExtract = new ExpHistory(pEH, NULL, (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), pList->get(0));
1095                             pEHExtract->setWhereReinsert((int)(pdblArgs[0] - 1));
1096                             workFields.push_back(pEHExtract);
1097                         }
1098                         else
1099                         {
1100                             // a(x).b
1101                             // extract a(x) and push_FRONT to extract b
1102                             ExpHistory* pEHExtract = new ExpHistory(pEH, pEH->getExp(), NULL, pEH->getLevel(), pEH->isCellExp(), pList->get(0));
1103                             pEHExtract->setWhereReinsert((int)(pdblArgs[0] - 1));
1104                             workFields.push_front(pEHExtract);
1105                         }
1106
1107                         //extract create a list to store items
1108                         pList->killMe();
1109                     }
1110                 }
1111                 else
1112                 {
1113                     // get string "x" of a.x
1114                     types::InternalType* pExtract = NULL;
1115                     std::wstring pwcsFieldname = L"";
1116                     bool bReinsert = false;
1117                     ExpHistory* pEHChield = NULL;
1118
1119                     pwcsFieldname = (*iterFields)->getExpAsString();
1120
1121                     // check if the field x is the last field
1122                     std::list<ExpHistory*>::iterator iterFieldsNext(iterFields);
1123                     ++iterFieldsNext;
1124                     if (iterFieldsNext == fields.end() && (*iterFields)->getArgs() == NULL)
1125                     {
1126                         // create pArg with "x" and set it as argument of "a"
1127                         types::typed_list* args = new types::typed_list();
1128                         args->push_back(new types::String(pwcsFieldname.c_str()));
1129                         pEH->setArgs(args);
1130
1131                         // a.x where x is the last field
1132                         // insert directly in x instead of extract then insert
1133                         ExpHistory* pEHNext = new ExpHistory(pEH, (*iterFields)->getExp(), (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), _pAssignValue);
1134                         pEHNext->setReinsertion(true);
1135                         evalFields.push_back(pEHNext);
1136                         if (workFields.empty())
1137                         {
1138                             break;
1139                         }
1140                     }
1141                     else
1142                     {
1143                         // check if field exists
1144                         if (pTL->exists(pwcsFieldname) == false)
1145                         {
1146                             std::list<ExpHistory*>::iterator iterFieldsNext(iterFields);
1147                             ++iterFieldsNext;
1148
1149                             if (iterFieldsNext != fields.end() || (*iterFields)->getArgs() != NULL)
1150                             {
1151                                 // M=mlist(['MType','x','y'], ...
1152                                 // M.rows1 = "somthing"
1153                                 pArgs = new types::typed_list();
1154                                 pArgs->push_back(new types::String(pwcsFieldname.c_str()));
1155
1156                                 // call overload
1157                                 pExtract = callOverload(*pEH->getExp(), L"6", pArgs, pTL, NULL);
1158                                 bReinsert = true;
1159
1160                                 delete pArgs;
1161                             }
1162                         }
1163                         else
1164                         {
1165                             // extract field x and append it to elements for next recursion.
1166                             pExtract = pTL->getField(pwcsFieldname);
1167                         }
1168
1169                         pEHChield = new ExpHistory(pEH, (*iterFields)->getExp(), (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), pExtract);
1170                         workFields.push_back(pEHChield);
1171
1172                         if (bReinsert)
1173                         {
1174                             pEHChield->setReinsertion();
1175                         }
1176                     }
1177                 }
1178             }
1179             else if (pITCurrent->isList())
1180             {
1181                 types::List* pL = pITCurrent->getAs<types::List>();
1182                 if (pEH->getParent() && pEH->getParent()->getLevel() == pEH->getLevel())
1183                 {
1184                     std::wostringstream os;
1185                     os << _W("Wrong insertion.");
1186                     throw ast::InternalError(os.str(), 999, _pExp->getLocation());
1187
1188                     //                    // pITCurrent is an extraction of other Type
1189                     //                    for (int iLoop = 0; iLoop < pL->getSize(); iLoop++)
1190                     //                    {
1191                     //                        ExpHistory* pEHExtract = new ExpHistory(pEH, pEH->getExp(), NULL, pEH->getLevel(), pEH->isCellExp(), pL->get(iLoop));
1192                     //                        pEHExtract->setWhereReinsert(iLoop);
1193                     //                        workFields.push_front(pEHExtract);
1194                     //                    }
1195                 }
1196                 else
1197                 {
1198                     // pITCurrent is a field
1199                     if (pEH->getArgs())
1200                     {
1201                         if (pEH->getArgs()->size() > 1)
1202                         {
1203                             // call overload
1204                             types::InternalType* pExtract = callOverload(*pEH->getExp(), L"6", pEH->getArgs(), pL, NULL);
1205
1206                             if ((*iterFields)->getExp() == NULL)
1207                             {
1208                                 // a(x)(y)
1209                                 // extract a(x) and push_BACK to extract next level
1210                                 workFields.push_back(new ExpHistory(pEH, NULL, (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), pExtract));
1211                                 workFields.back()->setReinsertion();
1212                             }
1213                             else
1214                             {
1215                                 // a(x).b
1216                                 // extract a(x) and push_FRONT to extract b from a(x)
1217                                 workFields.push_front(new ExpHistory(pEH, pEH->getExp(), NULL, pEH->getLevel(), pEH->isCellExp(), pExtract));
1218                                 workFields.front()->setReinsertion();
1219                             }
1220                         }
1221                         else
1222                         {
1223                             // resize List
1224                             int iNewSize = pEH->getSizeFromArgs();
1225                             if (pL->getSize() < iNewSize)
1226                             {
1227                                 pL = pL->set(iNewSize - 1, new types::Void());
1228                                 pEH->setCurrent(pL);
1229                             }
1230
1231                             types::Double* pDblArgs = (*pEH->getArgs())[0]->getAs<types::Double>();
1232                             double* pdblArgs = pDblArgs->get();
1233
1234                             if ((*iterFields)->getExp() == NULL)
1235                             {
1236                                 // a(x)(y) => a.b(y)
1237                                 // extract a(x) and push_BACK to extract next level
1238                                 for (int iLoop = 0; iLoop < pDblArgs->getSize(); iLoop++)
1239                                 {
1240                                     ExpHistory* pEHExtract = new ExpHistory(pEH, NULL, (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), pL->get((int)pdblArgs[iLoop] - 1));
1241                                     pEHExtract->setWhereReinsert((int)(pdblArgs[iLoop] - 1));
1242                                     workFields.push_back(pEHExtract);
1243                                 }
1244                             }
1245                             else
1246                             {
1247                                 // a(x).b
1248                                 // extract a(x) and push_FRONT to extract b from a(x)
1249                                 for (int iLoop = 0; iLoop < pDblArgs->getSize(); iLoop++)
1250                                 {
1251                                     ExpHistory* pEHExtract = new ExpHistory(pEH, pEH->getExp(), NULL, pEH->getLevel(), pEH->isCellExp(), pL->get((int)pdblArgs[iLoop] - 1));
1252                                     pEHExtract->setWhereReinsert((int)(pdblArgs[iLoop] - 1));
1253                                     workFields.push_front(pEHExtract);
1254                                 }
1255                             }
1256                         }
1257                     }
1258                     else
1259                     {
1260                         // a.x, get string "x"
1261                         std::wstring pwcsFieldname = (*iterFields)->getExpAsString();
1262
1263                         // create pArg with "x"
1264                         types::typed_list* args = new types::typed_list();
1265                         args->push_back(new types::String(pwcsFieldname.c_str()));
1266                         pEH->setArgs(args);
1267
1268                         // check if the field x is the last field
1269                         std::list<ExpHistory*>::iterator iterFieldsNext(iterFields);
1270                         ++iterFieldsNext;
1271                         if (iterFieldsNext == fields.end() && (*iterFields)->getArgs() == NULL)
1272                         {
1273                             // a.x where x is the last field
1274                             // insert directly in x instead of extract then insert
1275                             ExpHistory* pEHNext = new ExpHistory(pEH, (*iterFields)->getExp(), (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), _pAssignValue);
1276                             pEHNext->setReinsertion(true);
1277                             evalFields.push_back(pEHNext);
1278                             if (workFields.empty())
1279                             {
1280                                 break;
1281                             }
1282                         }
1283                         else
1284                         {
1285                             // call overload
1286                             types::InternalType* pExtract = callOverload(*pEH->getExp(), L"6", args, pL, NULL);
1287
1288                             // append extraction of a.x for next level.
1289                             workFields.push_back(new ExpHistory(pEH, (*iterFields)->getExp(), (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), pExtract));
1290                             workFields.back()->setReinsertion();
1291                         }
1292                     }
1293                 }
1294             }
1295             else if (pITCurrent->isHandle())
1296             {
1297                 types::typed_list* pArgs = pEH->getArgs();
1298                 types::GraphicHandle* pGH = pITCurrent->getAs<types::GraphicHandle>();
1299                 if (pArgs)
1300                 {
1301                     types::InternalType* pExtract = NULL;
1302
1303                     if (pArgs->size() == 1 && (*pArgs)[0]->isImplicitList() == false)
1304                     {
1305                         // call overload
1306                         pExtract = callOverload(*pEH->getExp(), L"e", pArgs, pITCurrent, NULL);
1307                     }
1308                     else
1309                     {
1310                         pExtract = pGH->extract(pArgs);
1311                     }
1312
1313                     if (pExtract == NULL)
1314                     {
1315                         std::wostringstream os;
1316                         os << _W("Invalid index.\n");
1317                         throw ast::InternalError(os.str(), 999, _pExp->getLocation());
1318                     }
1319
1320                     if ((*iterFields)->getExp() == NULL)
1321                     {
1322                         // a(x)(y)
1323                         // extract a(x) and push_BACK to extract next level
1324                         workFields.push_back(new ExpHistory(pEH, NULL, (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), pExtract));
1325                         workFields.back()->setReinsertion();
1326                     }
1327                     else
1328                     {
1329                         // a(x).b
1330                         // extract a(x) and push_FRONT to extract b from a(x)
1331                         workFields.push_front(new ExpHistory(pEH, pEH->getExp(), NULL, pEH->getLevel(), pEH->isCellExp(), pExtract));
1332                         workFields.front()->setReinsertion();
1333                     }
1334                 }
1335                 else
1336                 {
1337                     // a.x, get string "x"
1338                     std::wstring pwcsFieldname = (*iterFields)->getExpAsString();
1339
1340                     // create arg with next field
1341                     types::typed_list* args = new types::typed_list();
1342                     args->push_back(new types::String(pwcsFieldname.c_str()));
1343                     pEH->setArgs(args);
1344
1345                     // check if the field x is the last field
1346                     std::list<ExpHistory*>::iterator iterFieldsNext(iterFields);
1347                     ++iterFieldsNext;
1348                     if (iterFieldsNext == fields.end() && (*iterFields)->getArgs() == NULL)
1349                     {
1350                         // a.x where x is the last field
1351                         // insert directly in x instead of extract then insert
1352                         ExpHistory* pEHNext = new ExpHistory(pEH, (*iterFields)->getExp(), (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), _pAssignValue);
1353                         pEHNext->setReinsertion(true);
1354                         evalFields.push_back(pEHNext);
1355                         if (workFields.empty())
1356                         {
1357                             break;
1358                         }
1359                     }
1360                     else
1361                     {
1362                         // call overload
1363                         types::InternalType* pExtract = callOverload(*pEH->getExp(), L"e", args, pITCurrent, NULL);
1364
1365                         // append extraction of a.x for next level.
1366                         workFields.push_back(new ExpHistory(pEH, (*iterFields)->getExp(), (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), pExtract));
1367                         workFields.front()->setReinsertion();
1368                     }
1369                 }
1370             }
1371             else if (pITCurrent->isCell())
1372             {
1373                 if (pEH->getArgs() && (*pEH->getArgs())[0]->isString() == false)
1374                 {
1375                     if (pEH->isCellExp())
1376                     {
1377                         types::Cell* pCell = pITCurrent->getAs<types::Cell>();
1378                         // a{x} => extract like a(x){[1 2 ...]}
1379                         if (pEH->getParent() && pEH->getLevel() == pEH->getParent()->getLevel())
1380                         {
1381                             // extract each elements of a(x)
1382                             for (int iCell = 0; iCell < pCell->getSize(); iCell++)
1383                             {
1384                                 types::InternalType* pIT = pCell->get(iCell);
1385                                 if ((*iterFields)->getExp() == NULL)
1386                                 {
1387                                     // a{x}(y)
1388                                     ExpHistory* pEHChield = new ExpHistory(pEH, NULL, (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), pIT);
1389                                     pEHChield->setWhereReinsert(iCell);
1390                                     workFields.push_back(pEHChield);
1391                                 }
1392                                 else
1393                                 {
1394                                     // a{x}.b
1395                                     ExpHistory* pEHChield = new ExpHistory(pEH, pEH->getExp(), NULL, pEH->getLevel(), false, pIT);
1396                                     pEHChield->setWhereReinsert(iCell);
1397                                     workFields.push_front(pEHChield);
1398                                 }
1399                             }
1400                         }
1401                         else
1402                         {
1403                             types::GenericType* pCell = pITCurrent->getAs<types::GenericType>();
1404                             if (pEH->needResize())
1405                             {
1406                                 if (pEH->getArgsDims() == 1)
1407                                 {
1408                                     std::wostringstream os;
1409                                     os << _W("Invalid index.\n");
1410                                     throw ast::InternalError(os.str(), 999, _pExp->getLocation());
1411                                 }
1412
1413                                 // resize current Cell
1414                                 pCell = pCell->resize(pEH->getArgsDimsArray(), pEH->getArgsDims());
1415                                 pEH->setCurrent(pCell);
1416                             }
1417
1418                             types::InternalType* pIT = pCell->extract(pEH->getArgs());
1419                             workFields.push_front(new ExpHistory(pEH, pEH->getExp(), pEH->getArgs(), pEH->getLevel(), pEH->isCellExp(), pIT));
1420                             workFields.front()->setReinsertion();
1421                         }
1422                     }
1423                     else
1424                     {
1425                         if ((*iterFields)->isCellExp())
1426                         {
1427                             types::GenericType* pCell = pITCurrent->getAs<types::GenericType>();
1428
1429                             // a(x){y}
1430                             if (pEH->needResize())
1431                             {
1432                                 if (pEH->getArgsDims() == 1)
1433                                 {
1434                                     std::wostringstream os;
1435                                     os << _W("Invalid index.\n");
1436                                     throw ast::InternalError(os.str(), 999, _pExp->getLocation());
1437                                 }
1438
1439                                 // resize current Cell
1440                                 pCell = pCell->resize(pEH->getArgsDimsArray(), pEH->getArgsDims())->getAs<types::Cell>();
1441                                 pEH->setCurrent(pCell);
1442                             }
1443
1444                             types::InternalType* pIT = pCell->extract(pEH->getArgs());
1445                             workFields.push_back(new ExpHistory(pEH, (*iterFields)->getExp(), (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), pIT));
1446                             workFields.front()->setReinsertion();
1447                         }
1448                         else
1449                         {
1450                             // only a(x)
1451                             std::wostringstream os;
1452                             os << _W("Wrong insertion in a Cell.");
1453                             throw ast::InternalError(os.str(), 999, _pExp->getLocation());
1454                         }
1455                     }
1456                 }
1457                 else
1458                 {
1459                     std::wostringstream os;
1460                     os << _W("Wrong insertion in a Cell.");
1461                     throw ast::InternalError(os.str(), 999, _pExp->getLocation());
1462                 }
1463             }
1464             else if (pITCurrent->isUserType()) // not a Scilab defined datatype, access field after field
1465             {
1466                 // call userType extract method
1467                 if (pEH->getArgs())
1468                 {
1469                     // a(x)
1470                     types::InternalType* pExtract = pITCurrent->getAs<types::UserType>()->extract(pEH->getArgs());
1471                     if (pExtract == NULL)
1472                     {
1473                         // call overload
1474                         pExtract = callOverload(*pEH->getExp(), L"e", pEH->getArgs(), pITCurrent, NULL);
1475                     }
1476
1477                     if ((*iterFields)->getExp() == NULL)
1478                     {
1479                         // a(x)(y)
1480                         // extract a(x) and push_BACK to extract next level
1481                         workFields.push_back(new ExpHistory(pEH, NULL, (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), pExtract));
1482                         workFields.back()->setReinsertion();
1483                     }
1484                     else
1485                     {
1486                         // a(x).b
1487                         // extract a(x) and push_FRONT to extract b from a(x)
1488                         workFields.push_front(new ExpHistory(pEH, pEH->getExp(), NULL, pEH->getLevel(), pEH->isCellExp(), pExtract));
1489                         workFields.front()->setReinsertion();
1490                     }
1491                 }
1492                 else
1493                 {
1494                     // a.x, get string "x"
1495                     std::wstring pwcsFieldname = (*iterFields)->getExpAsString();
1496
1497                     // create arg with next field
1498                     types::typed_list* args = new types::typed_list();
1499                     args->push_back(new types::String(pwcsFieldname.c_str()));
1500                     pEH->setArgs(args);
1501
1502                     // check if the field x is the last field
1503                     std::list<ExpHistory*>::iterator iterFieldsNext(iterFields);
1504                     ++iterFieldsNext;
1505                     if (iterFieldsNext == fields.end() && (*iterFields)->getArgs() == NULL)
1506                     {
1507                         // a.x where x is the last field
1508                         // insert directly in x instead of extract then insert
1509                         ExpHistory* pEHNext = new ExpHistory(pEH, (*iterFields)->getExp(), (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), _pAssignValue);
1510                         pEHNext->setReinsertion(true);
1511                         evalFields.push_back(pEHNext);
1512                         if (workFields.empty())
1513                         {
1514                             break;
1515                         }
1516                     }
1517                     else
1518                     {
1519                         types::InternalType* pExtract = pITCurrent->getAs<types::UserType>()->extract(args);
1520                         if (pExtract == NULL)
1521                         {
1522                             // call overload
1523                             pExtract = callOverload(*pEH->getExp(), L"e", args, pITCurrent, NULL);
1524                         }
1525
1526                         // append extraction of a.x for next level.
1527                         workFields.push_back(new ExpHistory(pEH, (*iterFields)->getExp(), (*iterFields)->getArgs(), (*iterFields)->getLevel(), (*iterFields)->isCellExp(), pExtract));
1528                         workFields.back()->setReinsertion();
1529                     }
1530                 }
1531             }
1532             else if (pITCurrent->isCallable())
1533             {
1534                 bool ret = false;
1535                 types::typed_list out;
1536                 types::typed_list in;
1537                 types::optional_list opt;
1538
1539                 if (pEH->getArgs())
1540                 {
1541                     in = *pEH->getArgs();
1542                 }
1543
1544                 try
1545                 {
1546                     ret = pITCurrent->invoke(in, opt, 1, out, *pEH->getExp());
1547                 }
1548                 catch (ast::InternalAbort& ia)
1549                 {
1550                     throw ia;
1551                 }
1552                 catch (const ast::InternalError& ie)
1553                 {
1554                     throw ie;
1555                 }
1556
1557                 if (ret == false || out.size() != 1 || out[0]->isHandle() == false)
1558                 {
1559                     char szError[bsiz];
1560                     char* strFName = wide_string_to_UTF8(pITCurrent->getAs<types::Callable>()->getName().c_str());
1561                     os_sprintf(szError, _("Wrong insertion: insertion in output of '%s' is not allowed.\n"), strFName);
1562                     FREE(strFName);
1563
1564                     wchar_t* wError = to_wide_string(szError);
1565                     std::wstring err(wError);
1566                     FREE(wError);
1567
1568                     throw ast::InternalError(err, 999, pEH->getExp()->getLocation());
1569                 }
1570
1571                 pEH->setCurrent(out[0]);
1572                 pEH->setArgs(NULL);
1573                 pEH->resetReinsertion();
1574                 workFields.push_front(pEH);
1575                 evalFields.pop_back();
1576             }
1577             else
1578             {
1579                 types::InternalType* pIT = new types::Struct(1, 1);
1580                 pEH->setCurrent(pIT);
1581                 pEH->setReinsertion();
1582
1583                 workFields.push_front(pEH);
1584                 evalFields.pop_back();
1585             }
1586
1587             if (workFields.front()->getLevel() == (*iterFields)->getLevel())
1588             {
1589                 // go to next field
1590                 iterFields++;
1591             }
1592         }
1593
1594         //*** insert what we have to assign             ***//
1595         //*** in case where the last field is a CallExp ***//
1596         while (workFields.empty() == false)
1597         {
1598             ExpHistory* pEH = workFields.front();
1599             evalFields.push_back(pEH);
1600             workFields.pop_front();
1601
1602             types::typed_list* pArgs = pEH->getArgs();
1603
1604             // should never occur
1605             if (pArgs == NULL || pArgs->size() == 0)
1606             {
1607                 std::wostringstream os;
1608                 os << _W("Wrong insertion : Cannot insert without arguments.");
1609                 throw ast::InternalError(os.str(), 999, _pExp->getLocation());
1610             }
1611
1612             if (pEH->isCellExp())
1613             {
1614                 types::Cell* pCell = pEH->getCurrent()->getAs<types::Cell>();
1615                 // insert "something" in b{x}
1616                 if ((*pArgs)[0]->isString())
1617                 {
1618                     std::wostringstream os;
1619                     os << _W("Wrong insertion in a Cell.");
1620                     throw ast::InternalError(os.str(), 999, _pExp->getLocation());
1621                 }
1622
1623                 pCell->insertCell(pArgs, _pAssignValue);
1624             }
1625             else if (pEH->getCurrent() && pEH->getCurrent()->isCallable())
1626             {
1627                 std::wostringstream os;
1628                 os << _W("Unexpected redefinition of Scilab function.");
1629                 throw ast::InternalError(os.str(), 999, _pExp->getLocation());
1630             }
1631             else
1632             {
1633                 // insert "something" in b(x,y)
1634                 types::InternalType* pIT = insertionCall(*_pExp, pArgs, pEH->getCurrent(), _pAssignValue);
1635                 if (pIT == NULL)
1636                 {
1637                     std::wostringstream os;
1638                     os << _W("Submatrix incorrectly defined.\n");
1639                     throw ast::InternalError(os.str(), 999, _pExp->getLocation());
1640                 }
1641
1642                 pEH->setCurrent(pIT);
1643             }
1644         }
1645
1646         //*** update fields ***//
1647         while (evalFields.empty() == false)
1648         {
1649             ExpHistory* pEH = evalFields.back();
1650             if (pEH->reinsertMe())
1651             {
1652                 ExpHistory* pEHParent = pEH->getParent();
1653
1654                 if (pEHParent == NULL)
1655                 {
1656                     if (bPutInCtx)
1657                     {
1658                         pITMain->DecreaseRef();
1659                         pITMain->killMe();
1660                     }
1661
1662                     bPutInCtx = true;
1663                     pITMain = pEH->getCurrent();
1664                     pITMain->IncreaseRef();
1665                     break;
1666                 }
1667
1668                 types::typed_list* pParentArgs = pEHParent->getArgs();
1669                 if (pParentArgs == NULL || pEH->getWhereReinsert() != -1)
1670                 {
1671                     types::InternalType* pParent = pEHParent->getCurrent();
1672                     if (pParent->isStruct())
1673                     {
1674                         types::Struct* pStruct = pParent->getAs<types::Struct>();
1675                         pStruct->get(pEH->getWhereReinsert())->set(pEH->getExpAsString(), pEH->getCurrent());
1676                         evalFields.pop_back();
1677                         delete pEH;
1678                         continue;
1679                     }
1680                     else if (pParent->isTList() || pParent->isMList())
1681                     {
1682                         types::TList* pTL = pParent->getAs<types::TList>();
1683                         if (pParentArgs)
1684                         {
1685                             pTL = pTL->set(pEH->getWhereReinsert(), pEH->getCurrent());
1686                             pEHParent->setCurrent(pTL);
1687                             evalFields.pop_back();
1688                             delete pEH;
1689                             continue;
1690                         }
1691                         else
1692                         {
1693                             if (pTL->exists(pEH->getExpAsString()))
1694                             {
1695                                 pTL = pTL->set(pEH->getExpAsString(), pEH->getCurrent());
1696                                 pEHParent->setCurrent(pTL);
1697                                 evalFields.pop_back();
1698                                 delete pEH;
1699                                 continue;
1700                             }
1701
1702                             pParentArgs = new types::typed_list();
1703                             pParentArgs->push_back(new types::String(pEH->getExpAsString().c_str()));
1704                         }
1705                     }
1706                     else if (pParent->isCell())
1707                     {
1708                         types::Cell* pCell = pParent->getAs<types::Cell>();
1709                         if (pEHParent->isCellExp() && pEH->getWhereReinsert() != -1)
1710                         {
1711                             // a{x}.b => reinsert b in a{x}
1712                             pCell->set(pEH->getWhereReinsert(), pEH->getCurrent());
1713                             pEHParent->setReinsertion();
1714                             evalFields.pop_back();
1715                             delete pEH;
1716                             continue;
1717                         }
1718                     }
1719                 }
1720
1721                 types::InternalType* pIT = insertionCall(*_pExp, pParentArgs, pEHParent->getCurrent(), pEH->getCurrent());
1722                 if (pIT == NULL)
1723                 {
1724                     std::wostringstream os;
1725                     os << _W("Submatrix incorrectly defined.\n");
1726                     throw ast::InternalError(os.str(), 999, _pExp->getLocation());
1727                 }
1728
1729                 pEHParent->setCurrent(pIT);
1730                 if (pEHParent->getArgs() == NULL)
1731                 {
1732                     delete pParentArgs;
1733                 }
1734             }
1735
1736             if (pEH->getCurrent())
1737             {
1738                 pEH->getCurrent()->killMe();
1739             }
1740
1741             evalFields.pop_back();
1742             delete pEH;
1743         }
1744
1745         if (bPutInCtx)
1746         {
1747             pITMain->DecreaseRef();
1748             ctx->put(spMainExp->getStack(), pITMain);
1749         }
1750
1751         if (!evalFields.empty())
1752         {
1753             for (std::list<ExpHistory*>::const_iterator i = evalFields.begin(), end = evalFields.end(); i != end; i++)
1754             {
1755                 delete *i;
1756             }
1757         }
1758
1759         return pITMain;
1760     }
1761     catch (const ast::InternalError& error)
1762     {
1763         if (bPutInCtx)
1764         {
1765             pITMain->DecreaseRef();
1766         }
1767
1768         for (std::list<ExpHistory*>::reverse_iterator i = workFields.rbegin(); i != workFields.rend(); ++i)
1769         {
1770             (*i)->setDeleteCurrent(true);
1771             delete *i;
1772         }
1773
1774         for (std::list<ExpHistory*>::reverse_iterator i = evalFields.rbegin(); i != evalFields.rend(); ++i)
1775         {
1776             (*i)->setDeleteCurrent(true);
1777             delete *i;
1778         }
1779
1780         throw error;
1781     }
1782 }
1783
1784 types::InternalType* insertionCall(const ast::Exp& e, types::typed_list* _pArgs, types::InternalType* _pVar, types::InternalType* _pInsert)
1785 {
1786     types::InternalType* pOut = NULL;
1787     types::InternalType *pIL = NULL;
1788     //fisrt extract implicit list
1789     if (_pInsert->isColon())
1790     {
1791         //double* pdbl = NULL;
1792         //_pInsert = new Double(-1, -1, &pdbl);
1793         //pdbl[0] = 1;
1794         pIL = types::Double::Identity(-1, -1);
1795         _pInsert->killMe();
1796         _pInsert = pIL;
1797     }
1798     else if (_pInsert->isImplicitList())
1799     {
1800         pIL = _pInsert->getAs<types::ImplicitList>()->extractFullMatrix();
1801         if (pIL && pIL->isDeletable())
1802         {
1803             _pInsert->killMe();
1804             _pInsert = pIL;
1805         }
1806     }
1807     else if (_pInsert->isContainer() && _pInsert->isRef())
1808     {
1809         //std::cout << "assign container type during insertion" << std::endl;
1810         //types::InternalType* pIL = _pInsert->clone();
1811         //_pInsert = pIL;
1812     }
1813
1814     if (_pInsert->isDouble() && _pInsert->getAs<types::Double>()->isEmpty() && _pVar == NULL)
1815     {
1816         // l(x) = [] when l is not defined => create l = []
1817         pOut = types::Double::Empty();
1818     }
1819     else if (_pInsert->isDouble() && _pInsert->getAs<types::Double>()->isEmpty() && _pVar->isStruct() == false && _pVar->isList() == false)
1820     {
1821         //insert [] so deletion except for Struct and List which can insert []
1822         if (_pVar->isHandle())
1823         {
1824             types::GraphicHandle* pH = _pVar->getAs<types::GraphicHandle>();
1825             if ((*_pArgs)[0]->isString())
1826             {
1827                 types::String *pS = (*_pArgs)[0]->getAs<types::String>();
1828
1829                 types::typed_list in;
1830                 types::typed_list out;
1831                 types::optional_list opt;
1832
1833                 in.push_back(pH);
1834                 in.push_back(pS);
1835                 in.push_back(_pInsert);
1836
1837                 types::Function* pCall = (types::Function*)symbol::Context::getInstance()->get(symbol::Symbol(L"set"));
1838                 types::Callable::ReturnValue ret = pCall->call(in, opt, 1, out);
1839                 if (ret == types::Callable::OK)
1840                 {
1841                     pOut = _pVar;
1842                 }
1843             }
1844             else
1845             {
1846                 pOut = pH->remove(_pArgs);
1847             }
1848         }
1849         else if (_pVar->isStruct())
1850         {
1851             pOut = _pVar->getAs<types::Struct>()->insert(_pArgs, _pInsert);
1852         }
1853         else if (_pVar->isUserType())
1854         {
1855             pOut = _pVar->getAs<types::UserType>()->insert(_pArgs, _pInsert);
1856         }
1857         else if (_pInsert->isGenericType() && (_pInsert->isTList() == false && _pInsert->isMList() == false))
1858         {
1859             pOut = _pVar->getAs<types::GenericType>()->remove(_pArgs);
1860         }
1861         else
1862         {
1863             //overload !
1864             pOut = callOverload(e, L"i", _pArgs, _pInsert, _pVar);
1865         }
1866     }
1867     else if (_pArgs->size() > 0 && (_pVar == NULL || (_pVar->isDouble() && _pVar->getAs<types::Double>()->getSize() == 0)))
1868     {
1869         //insert in a new variable or []
1870         //call static insert function
1871         //if _pVar == NULL and pArg is single string, it's a struct creation
1872         if ((*_pArgs)[0]->isString())
1873         {
1874             types::String *pS = (*_pArgs)[0]->getAs<types::String>();
1875
1876             if (_pArgs->size() != 1 || pS->isScalar() == false)
1877             {
1878                 if (pIL)
1879                 {
1880                     pIL->killMe();
1881                 }
1882                 //manage error
1883                 std::wostringstream os;
1884                 os << _W("Invalid index.\n");
1885                 throw ast::InternalError(os.str(), 999, e.getLocation());
1886             }
1887
1888             types::Struct* pStr = new types::Struct(1, 1);
1889             pStr->addField(pS->get(0));
1890             pStr->get(0)->set(pS->get(0), _pInsert);
1891             pOut = pStr;
1892         }
1893         else
1894         {
1895             if (_pInsert->isGenericType() && (_pInsert->isTList() == false && _pInsert->isMList() == false))
1896             {
1897                 pOut = _pInsert->getAs<types::GenericType>()->insertNew(_pArgs);
1898             }
1899             else
1900             {
1901                 // overload
1902                 types::Double* pEmpty = types::Double::Empty();
1903                 pOut = callOverload(e, L"i", _pArgs, _pInsert, pEmpty);
1904                 pEmpty->killMe();
1905             }
1906         }
1907     }
1908     else
1909     {
1910         //call type insert function
1911         types::InternalType* pRet = NULL;
1912
1913         // case m=x; m()=x;
1914         if (_pArgs == NULL || _pArgs->size() == 0)
1915         {
1916             std::wostringstream os;
1917             os << _W("Wrong insertion : Cannot insert without arguments.");
1918             throw ast::InternalError(os.str(), 999, e.getLocation());
1919         }
1920
1921         //check types compatibilties
1922         if (_pVar->isDouble() && _pInsert->isSparse())
1923         {
1924             types::Sparse* pSp = _pInsert->getAs<types::Sparse>();
1925             types::Double* pD = new types::Double(pSp->getRows(), pSp->getCols(), pSp->isComplex());
1926             pSp->fill(*pD);
1927             pRet = _pVar->getAs<types::GenericType>()->insert(_pArgs, pD);
1928             delete pD;
1929         }
1930         else if (_pVar->isSparse() && _pInsert->isDouble())
1931         {
1932             pRet = _pVar->getAs<types::GenericType>()->insert(_pArgs, _pInsert);
1933         }
1934         else if (_pVar->isSparseBool() && _pInsert->isBool())
1935         {
1936             pRet = _pVar->getAs<types::GenericType>()->insert(_pArgs, _pInsert);
1937         }
1938         else if (_pVar->isDouble() && _pInsert->isPoly())
1939         {
1940             types::Double* pDest = _pVar->getAs<types::Double>();
1941             types::Polynom* pIns = _pInsert->getAs<types::Polynom>();
1942             int iSize = pDest->getSize();
1943             int* piRanks = new int[iSize];
1944             memset(piRanks, 0x00, iSize * sizeof(int));
1945             types::Polynom* pP = new types::Polynom(pIns->getVariableName(), pDest->getDims(), pDest->getDimsArray(), piRanks);
1946             delete[] piRanks;
1947             pP->setComplex(pDest->isComplex());
1948
1949             if (pP->isComplex())
1950             {
1951                 for (int idx = 0; idx < pP->getSize(); idx++)
1952                 {
1953                     double dblR = pDest->get(idx);
1954                     double dblI = pDest->getImg(idx);
1955                     pP->get(idx)->setCoef(&dblR, &dblI);
1956                 }
1957             }
1958             else
1959             {
1960                 for (int idx = 0; idx < pP->getSize(); idx++)
1961                 {
1962                     double dblR = pDest->get(idx);
1963                     pP->get(idx)->setCoef(&dblR, NULL);
1964                 }
1965             }
1966
1967             pRet = pP->insert(_pArgs, pIns);
1968         }
1969         else if (_pVar->isPoly() && _pInsert->isDouble())
1970         {
1971             types::Polynom* pDest = _pVar->getAs<types::Polynom>();
1972             types::Double* pIns = _pInsert->getAs<types::Double>();
1973             bool isComplexIns = pIns->isComplex();
1974             int iSize = pIns->getSize();
1975             int* piRanks = new int[iSize];
1976             memset(piRanks, 0x00, iSize * sizeof(int));
1977
1978             //create a new polynom with Double to insert it into dest polynom
1979             types::Polynom* pP = new types::Polynom(pDest->getVariableName(), pIns->getDims(), pIns->getDimsArray(), piRanks);
1980             delete[] piRanks;
1981
1982             if (isComplexIns)
1983             {
1984                 double* pR = pIns->get();
1985                 double* pI = pIns->getImg();
1986                 types::SinglePoly** pSP = pP->get();
1987                 for (int idx = 0; idx < pP->getSize(); idx++)
1988                 {
1989                     double dblR = pR[idx];
1990                     double dblI = pI[idx];
1991                     pSP[idx]->setComplex(true);
1992                     pSP[idx]->setCoef(&dblR, &dblI);
1993                 }
1994             }
1995             else
1996             {
1997                 double* pdblR = pIns->get();
1998                 types::SinglePoly** pSP = pP->get();
1999                 for (int idx = 0; idx < pP->getSize(); idx++)
2000                 {
2001                     double dblR = pdblR[idx];
2002                     pSP[idx]->setCoef(&dblR, NULL);
2003                 }
2004             }
2005
2006             pRet = pDest->insert(_pArgs, pP);
2007             pP->killMe();
2008         }
2009         else if (_pVar->isStruct())
2010         {
2011             types::Struct* pStruct = _pVar->getAs<types::Struct>();
2012             // insert something in a field of a struct
2013             if (_pArgs->size() == 1 && (*_pArgs)[0]->isString())
2014             {
2015                 //s("x") = y
2016                 types::String *pS = (*_pArgs)[0]->getAs<types::String>();
2017                 if (pS->isScalar() == false)
2018                 {
2019                     if (pIL)
2020                     {
2021                         pIL->killMe();
2022                     }
2023                     //manage error
2024                     std::wostringstream os;
2025                     os << _W("Invalid index.\n");
2026                     throw ast::InternalError(os.str(), 999, e.getLocation());
2027                 }
2028
2029                 if (_pInsert->isListDelete())
2030                 {
2031                     /* Remove a field */
2032                     pStruct = pStruct->removeField(pS->get(0));
2033                 }
2034                 else
2035                 {
2036                     /* Add a field */
2037                     pStruct = pStruct->addField(pS->get(0));
2038                     for (int i = 0; i < pStruct->getSize(); i++)
2039                     {
2040                         pStruct->get(i)->set(pS->get(0), _pInsert);
2041                     }
2042                 }
2043                 pRet = pStruct;
2044             }
2045             else // insert something in a struct
2046             {
2047                 if (_pInsert->isStruct() && _pInsert->getAs<types::Struct>()->isEmpty() == false)
2048                 {
2049                     types::String* pStrFieldsName = pStruct->getFieldNames();
2050                     types::Struct* pStructInsert = _pInsert->clone()->getAs<types::Struct>();
2051                     types::String* pStrInsertFieldsName = pStructInsert->getFieldNames();
2052                     types::Struct* pStructRet = NULL;
2053
2054                     // if not an empty struct
2055                     if (pStrFieldsName)
2056                     {
2057                         // insert fields of pStruct in pStructInsert
2058                         for (int i = pStrFieldsName->getSize(); i > 0; i--)
2059                         {
2060                             if (pStructInsert->exists(pStrFieldsName->get(i - 1)) == false)
2061                             {
2062                                 pStructInsert->addFieldFront(pStrFieldsName->get(i - 1));
2063                             }
2064                             else
2065                             {
2066                                 std::wstring pwcsField = pStrFieldsName->get(i - 1);
2067                                 types::List* pLExtract = pStructInsert->extractFieldWithoutClone(pwcsField);
2068
2069                                 for (int i = 0; i < pLExtract->getSize(); i++)
2070                                 {
2071                                     // protect element wich are not cloned before call removeField.
2072                                     pLExtract->get(i)->IncreaseRef();
2073                                 }
2074
2075                                 pStructInsert->removeField(pwcsField);
2076                                 pStructInsert->addFieldFront(pwcsField);
2077
2078                                 for (int i = 0; i < pLExtract->getSize(); i++)
2079                                 {
2080                                     // set elements in the new position
2081                                     pStructInsert->get(i)->set(pwcsField, pLExtract->get(i));
2082                                     pLExtract->get(i)->DecreaseRef();
2083                                 }
2084
2085                                 pLExtract->killMe();
2086                             }
2087                         }
2088
2089                         pStrFieldsName->killMe();
2090                     }
2091                     else if (pStrInsertFieldsName)
2092                     {
2093                         //insertion of non-empty struct in empty struct
2094                         for (int i = pStrInsertFieldsName->getSize(); i > 0; i--)
2095                         {
2096                             pStruct->addFieldFront(pStrInsertFieldsName->get(i - 1));
2097                         }
2098                     }
2099
2100                     // insert elements in following pArgs
2101                     pRet = pStruct->insert(_pArgs, pStructInsert);
2102                     pStructRet = pRet->getAs<types::Struct>();
2103
2104                     pStructInsert->killMe();
2105
2106                     // if not an empty struct
2107                     if (pStrFieldsName)
2108                     {
2109                         // insert fields of pStructInsert in pRet
2110                         for (int i = 0; i < pStrInsertFieldsName->getSize(); i++)
2111                         {
2112                             if (pStructRet->exists(pStrInsertFieldsName->get(i)) == false)
2113                             {
2114                                 pStructRet->addField(pStrInsertFieldsName->get(i));
2115                             }
2116                         }
2117                     }
2118                     pStrInsertFieldsName->killMe();
2119                 }
2120                 else if (_pInsert->isStruct())
2121                 {
2122                     // insertion of empty struct in a struct
2123                     pRet = pStruct;
2124                 }
2125                 else if (_pInsert->isDouble() && _pInsert->getAs<types::Double>()->isEmpty())
2126                 {
2127                     pRet = pStruct->remove(_pArgs);
2128                 }
2129                 else
2130                 {
2131                     pRet = callOverload(e, L"i", _pArgs, _pInsert, _pVar);
2132                 }
2133             }
2134         }
2135         else if (_pVar->isTList() || _pVar->isMList())
2136         {
2137             types::TList* pTL = _pVar->getAs<types::TList>();
2138             if (_pArgs->size() == 1)
2139             {
2140                 if ((*_pArgs)[0]->isString())
2141                 {
2142                     //s("x") = y
2143                     types::String *pS = (*_pArgs)[0]->getAs<types::String>();
2144                     if (pS->isScalar() == false)
2145                     {
2146                         if (pIL)
2147                         {
2148                             pIL->killMe();
2149                         }
2150
2151                         //manage error
2152                         std::wostringstream os;
2153                         os << _W("Invalid index.\n");
2154                         throw ast::InternalError(os.str(), 999, e.getLocation());
2155                     }
2156
2157                     if (_pInsert->isListDelete())
2158                     {
2159                         return callOverload(e, L"i", _pArgs, _pInsert, _pVar);
2160                     }
2161
2162                     if (pTL->exists(pS->get(0)))
2163                     {
2164                         pRet = pTL->set(pS->get(0), _pInsert);
2165                     }
2166                     else
2167                     {
2168                         return callOverload(e, L"i", _pArgs, _pInsert, _pVar);
2169
2170                         //ExecVisitor exec;
2171                         //typed_list in;
2172                         //typed_list out;
2173                         //std::wstring function_name = L"%l_e";
2174
2175                         //_pInsert->IncreaseRef();
2176                         //in.push_back(_pInsert);
2177
2178                         //Overload::call(function_name, in, 1, out, &exec);
2179                         //_pInsert->DecreaseRef();
2180
2181                         //if (out.size() != 0)
2182                         //{
2183                         //    pRet = in[0];
2184                         //}
2185                     }
2186                 }
2187                 else
2188                 {
2189                     // s(x)
2190                     if (_pVar->isMList())
2191                     {
2192                         pRet = callOverload(e, L"i", _pArgs, _pInsert, _pVar);
2193                     }
2194                     else
2195                     {
2196                         // In case where pTL is in several scilab variable,
2197                         // we have to clone it for keep the other variables unchanged.
2198                         if (pTL->getRef() > 1)
2199                         {
2200                             pTL = pTL->clone()->getAs<types::TList>();
2201                         }
2202
2203                         pRet = pTL->insert(_pArgs, _pInsert);
2204
2205                         // If we have inserted something else than a String
2206                         // in the first element, the TList have to be a List.
2207                         if (pTL->get(0)->isString() == false)
2208                         {
2209                             types::List* pL = new types::List();
2210                             for (int i = 0; i < pTL->getSize(); i++)
2211                             {
2212                                 pL->append(pTL->get(i));
2213                             }
2214
2215                             pTL->killMe();
2216                             pRet = pL;
2217                         }
2218                     }
2219                 }
2220             }
2221             else
2222             {
2223                 if (_pVar->isMList())
2224                 {
2225                     pRet = callOverload(e, L"i", _pArgs, _pInsert, _pVar);
2226                 }
2227                 else
2228                 {
2229                     // call the overload if it exists.
2230                     pRet = callOverload(e, L"i", _pArgs, _pInsert, _pVar);
2231                     if (pRet == NULL)
2232                     {
2233                         // else normal insert
2234                         pRet = pTL->insert(_pArgs, _pInsert);
2235                     }
2236                 }
2237             }
2238         }
2239         else if (_pVar->isList())
2240         {
2241             types::List* pL = NULL;
2242             // In case where pL is in several scilab variable,
2243             // we have to clone it for keep the other variables unchanged.
2244             if (_pVar->getRef() > 1)
2245             {
2246                 pL = _pVar->clone()->getAs<types::List>();
2247                 pRet = pL->insert(_pArgs, _pInsert);
2248                 if (pRet == NULL)
2249                 {
2250                     pL->killMe();
2251                     // call overload
2252                     pRet = callOverload(e, L"i", _pArgs, _pInsert, _pVar);
2253                 }
2254             }
2255             else
2256             {
2257                 pL = _pVar->getAs<types::List>();
2258                 pRet = pL->insert(_pArgs, _pInsert);
2259                 if (pRet == NULL)
2260                 {
2261                     // call overload
2262                     pRet = callOverload(e, L"i", _pArgs, _pInsert, _pVar);
2263                 }
2264             }
2265         }
2266         else if (_pVar->isHandle())
2267         {
2268             if (_pArgs->size() == 1 && (*_pArgs)[0]->isString())
2269             {
2270                 //s(["x"])
2271                 types::GraphicHandle* pH = _pVar->getAs<types::GraphicHandle>();
2272                 types::String *pS = (*_pArgs)[0]->getAs<types::String>();
2273                 types::typed_list in;
2274                 types::typed_list out;
2275                 types::optional_list opt;
2276
2277                 in.push_back(pH);
2278                 in.push_back(pS);
2279                 in.push_back(_pInsert);
2280
2281                 types::Function* pCall = (types::Function*)symbol::Context::getInstance()->get(symbol::Symbol(L"set"));
2282                 if (pCall)
2283                 {
2284                     types::Callable::ReturnValue ret = pCall->call(in, opt, 1, out);
2285                     if (ret == types::Callable::OK)
2286                     {
2287                         pRet = _pVar;
2288                     }
2289                     else
2290                     {
2291                         throw ast::InternalError(ConfigVariable::getLastErrorMessage(), ConfigVariable::getLastErrorNumber(), e.getLocation());
2292                     }
2293                 }
2294             }
2295             else
2296             {
2297                 pRet = _pVar->getAs<types::GraphicHandle>()->insert(_pArgs, _pInsert);
2298             }
2299         }
2300         else if (_pVar->isUserType())
2301         {
2302             for (int i = 0; i < _pArgs->size(); i++)
2303             {
2304                 if ((*_pArgs)[i]->isImplicitList())
2305                 {
2306                     types::ImplicitList* pIL = (*_pArgs)[i]->getAs<types::ImplicitList>();
2307                     if (pIL->isComputable())
2308                     {
2309                         types::InternalType* pIT = pIL->extractFullMatrix();
2310                         (*_pArgs)[i]->killMe();
2311                         (*_pArgs)[i] = pIT;
2312                     }
2313                 }
2314             }
2315
2316             pRet = _pVar->getAs<types::UserType>()->insert(_pArgs, _pInsert);
2317             if (pRet == NULL)
2318             {
2319                 pRet = callOverload(e, L"i", _pArgs, _pInsert, _pVar);
2320             }
2321         }
2322         else if (_pVar->getType() == _pInsert->getType())
2323         {
2324             pRet = _pVar->getAs<types::GenericType>()->insert(_pArgs, _pInsert);
2325         }
2326         else if (_pVar->isCell())
2327         {
2328             if (_pInsert->isCell() == false)
2329             {
2330                 //manage error
2331                 std::wostringstream os;
2332                 os << _W("Wrong insertion: A Cell expected: use {...} instead of (...).\n");
2333                 throw ast::InternalError(os.str(), 999, e.getLocation());
2334             }
2335         }
2336         else
2337         {
2338             // overload
2339             pRet = callOverload(e, L"i", _pArgs, _pInsert, _pVar);
2340         }
2341
2342         pOut = pRet;
2343     }
2344
2345     if (pIL && pIL != pOut)
2346     {
2347         pIL->killMe();
2348     }
2349
2350     return pOut;
2351 }
2352
2353 void callOnPrompt(void)
2354 {
2355     static symbol::Variable* onPrompt = NULL;
2356     if (onPrompt == NULL)
2357     {
2358         onPrompt = symbol::Context::getInstance()->getOrCreate(symbol::Symbol(L"%onprompt"));
2359     }
2360
2361     types::InternalType* pOnPrompt = NULL;
2362     pOnPrompt = onPrompt->get();
2363     if (pOnPrompt != NULL && pOnPrompt->isCallable())
2364     {
2365         StoreConsoleCommand("%onprompt()", 1);
2366     }
2367 }
2368
2369 ast::Exp* callTyper(ast::Exp* _tree, std::wstring _msg)
2370 {
2371     ast::Exp* newTree = NULL;
2372     unsigned char *newast = NULL;
2373     ast::SerializeVisitor* s = new ast::SerializeVisitor(_tree);
2374     ast::DeserializeVisitor* d = NULL;
2375
2376     if (_msg.empty())
2377     {
2378         unsigned char* astbin = s->serialize();
2379         //call ocamlpro typer
2380         //char *newast = ocamlpro_typer(astbin);
2381
2382         //for debug
2383         newast = astbin;
2384
2385         d = new ast::DeserializeVisitor(newast);
2386         newTree = d->deserialize();
2387     }
2388     else
2389     {
2390         std::wstring msgS(_msg + L" serialize");
2391         std::wstring msgD(_msg + L" deserialize");
2392
2393         Timer timer;
2394         timer.start();
2395         unsigned char* astbin = s->serialize();
2396         timer.check(msgS.c_str());
2397
2398         //call ocamlpro typer
2399         //char *newast = ocamlpro_typer(astbin);
2400
2401         //for debug
2402         newast = astbin;
2403
2404         timer.start();
2405         d = new ast::DeserializeVisitor(newast);
2406         newTree = d->deserialize();
2407         timer.check(msgD.c_str());
2408     }
2409
2410     delete s;
2411     delete d;
2412     return newTree;
2413 }
2414
2415 std::string printExp(std::ifstream& _File, ast::Exp* _pExp, const std::string& _stPrompt, int* _piLine /* in/out */, int* _piCol /* in/out */, std::string& _stPreviousBuffer)
2416 {
2417     Location loc = _pExp->getLocation();
2418
2419     //get current line
2420     //for multiple expression on same line
2421     //_stPreviousBuffer will not be updated
2422
2423     //bypass previous lines
2424     for (int i = *_piLine; i < loc.first_line - 1; i++)
2425     {
2426
2427         (*_piLine)++;
2428         if ((*_piLine) != (loc.first_line - 1))
2429         {
2430             //empty line
2431             if (ConfigVariable::isPrintCompact() == false)
2432             {
2433                 printLine("", "", true);
2434             }
2435         }
2436         std::getline(_File, _stPreviousBuffer);
2437     }
2438
2439     if (loc.first_line == loc.last_line)
2440     {
2441         //expression on 1-line
2442         int iStart = loc.first_column - 1;
2443         int iEnd = loc.last_column - 1;
2444         int iLen = iEnd - iStart;
2445
2446         int iCopyLen = iEnd - *_piCol;
2447         std::string strLastLine(_stPreviousBuffer.c_str() + *_piCol, iCopyLen);
2448         int iExpLen = iLen;
2449         int iLineLen = (int)_stPreviousBuffer.size();
2450         bool bStart = iStart == 0 || *_piCol == 0;
2451         bool bEnd = iStart + iExpLen == iLineLen;
2452
2453         //begin of line
2454         if (bStart)
2455         {
2456             if (bEnd)
2457             {
2458                 printLine(_stPrompt, strLastLine, true);
2459                 *_piCol = 0;
2460             }
2461             else
2462             {
2463                 printLine(_stPrompt, strLastLine, false);
2464                 *_piCol = loc.last_column - 1;
2465             }
2466         }
2467         else //middle of line
2468         {
2469             if (bEnd)
2470             {
2471                 printLine("", strLastLine, true);
2472                 *_piCol = 0;
2473             }
2474             else
2475             {
2476                 printLine("", strLastLine, false);
2477                 *_piCol = loc.last_column - 1;
2478             }
2479         }
2480     }
2481     else
2482     {
2483         //multiline
2484         int iStart = loc.first_column - 1;
2485         bool bStart = iStart == 0 || *_piCol == 0;
2486
2487         std::string strLastLine(_stPreviousBuffer.c_str() + *_piCol);
2488
2489         //begin of line
2490         if (bStart)
2491         {
2492             printLine(_stPrompt, strLastLine, true);
2493         }
2494         else
2495         {
2496             printLine("", strLastLine, true);
2497         }
2498
2499         bool isCompact = ConfigVariable::isPrintCompact();
2500         ConfigVariable::setPrintCompact(true);
2501
2502         //full lines
2503         for (int i = loc.first_line; i < (loc.last_line - 1); i++)
2504         {
2505             (*_piLine)++;
2506             std::getline(_File, _stPreviousBuffer);
2507             // dont print empty line of function body
2508             if (_stPreviousBuffer.size() != 0)
2509             {
2510                 printLine(_stPrompt, _stPreviousBuffer.c_str(), true);
2511             }
2512         }
2513
2514         //last line
2515         std::getline(_File, _stPreviousBuffer);
2516         (*_piLine)++;
2517
2518         int iSize = loc.last_column - 1;
2519         std::string stLastLine(_stPreviousBuffer.c_str(), iSize);
2520         int iLineLen = (int)_stPreviousBuffer.size();
2521         if (iLineLen == iSize)
2522         {
2523             printLine(_stPrompt, stLastLine, true);
2524             *_piCol = 0;
2525         }
2526         else
2527         {
2528             printLine(_stPrompt, stLastLine, false);
2529             *_piCol = loc.last_column - 1;
2530         }
2531
2532         ConfigVariable::setPrintCompact(isCompact);
2533     }
2534
2535     return _stPreviousBuffer;
2536 }
2537
2538 void printLine(const std::string& _stPrompt, const std::string& _stLine, bool _bLF)
2539 {
2540     std::string st;
2541     int size = _stPrompt.size();
2542     if (size && ConfigVariable::isPrintCompact() == false)
2543     {
2544         st = "\n";
2545     }
2546
2547     st += _stPrompt;
2548
2549     st += _stLine;
2550     if (_bLF)
2551     {
2552         st += "\n";
2553     }
2554
2555     scilabWrite(st.c_str());
2556 }
2557 /*--------------------------------------------------------------------------*/