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