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