fix sparse module tests
[scilab.git] / scilab / modules / ast / src / cpp / ast / run_AssignExp.hpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2008-2008 - DIGITEO - Antoine ELIAS
4 *
5 *  This file must be used under the terms of the CeCILL.
6 *  This source file is licensed as described in the file COPYING, which
7 *  you should have received as part of this distribution.  The terms
8 *  are also available at
9 *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10 *
11 */
12
13 //file included in runvisitor.cpp
14 namespace ast {
15
16 template<class T>
17 void RunVisitorT<T>::visitprivate(const AssignExp  &e)
18 {
19     CoverageInstance::invokeAndStartChrono((void*)&e);
20     symbol::Context* ctx = symbol::Context::getInstance();
21     /*Create local exec visitor*/
22     try
23     {
24         SimpleVar * pVar = NULL;
25         if (e.getLeftExp().isSimpleVar())
26         {
27             pVar = static_cast<SimpleVar*>(&e.getLeftExp());
28         }
29
30         /*get king of left hand*/
31         if (pVar)
32         {
33             // x = ?
34             /*getting what to assign*/
35             types::InternalType *pIT = e.getRightVal();
36             if (pIT == NULL)
37             {
38                 setExpectedSize(1);
39                 e.getRightExp().accept(*this);
40
41                 if (getResultSize() != 1)
42                 {
43                     std::wostringstream os;
44                     os << _W("Can not assign multiple value in a single variable") << std::endl;
45                     //os << ((Location)e.getRightExp().getLocation()).getLocationString() << std::endl;
46                     throw ast::InternalError(os.str(), 999, e.getRightExp().getLocation());
47                 }
48
49                 pIT = getResult();
50                 //reset result
51                 setResult(NULL);
52             }
53
54             if (pIT->isImplicitList())
55             {
56                 if (pIT->getAs<types::ImplicitList>()->isComputable())
57                 {
58                     types::InternalType *pTemp = pIT->getAs<types::ImplicitList>()->extractFullMatrix();
59                     pIT->killMe();
60                     pIT = pTemp;
61                 }
62             }
63
64             if (pIT->isAssignable() == false)
65             {
66                 if (pIT->isListDelete())
67                 {
68                     //used to delete a variable in current scope
69                     symbol::Symbol sym = pVar->getSymbol();
70                     if (ctx->isprotected(sym) == false)
71                     {
72                         ctx->remove(sym);
73                     }
74                     else
75                     {
76                         std::wostringstream os;
77                         os << _W("Redefining permanent variable.\n");
78                         throw ast::InternalError(os.str(), 999, e.getLeftExp().getLocation());
79                     }
80                 }
81
82                 setResult(NULL);
83                 CoverageInstance::stopChrono((void*)&e);
84                 return;
85             }
86
87             if (pIT->isList() && pIT->getRef() > 0)
88             {
89                 // Prevent modification of all scilab variable
90                 // which point to this container when it is used
91                 // in setfield scilab function.
92                 // A clone on a container will not clone what it contain.
93                 pIT = pIT->clone();
94             }
95
96             if (e.getRightExp().isReturnExp())
97             {
98                 //ReturnExp so, put the value in the previous scope
99                 if (ctx->putInPreviousScope(pVar->getStack(), pIT) == false)
100                 {
101                     char pstError[1024];
102                     char* pstFuncName = wide_string_to_UTF8(pVar->getSymbol().getName().data());
103                     os_sprintf(pstError, _("It is not possible to redefine the %s primitive this way (see clearfun).\n"), pstFuncName);
104                     wchar_t* pwstError = to_wide_string(pstError);
105                     std::wstring wstError(pwstError);
106                     FREE(pstFuncName);
107                     FREE(pwstError);
108                     pIT->killMe();
109                     CoverageInstance::stopChrono((void*)&e);
110                     throw InternalError(wstError, 999, e.getLocation());
111                 }
112
113                 ((AssignExp*)&e)->setReturn();
114             }
115             else
116             {
117                 if (ctx->isprotected(pVar->getStack()) == false)
118                 {
119                     ctx->put(pVar->getStack(), pIT);
120                 }
121                 else
122                 {
123                     std::wostringstream os;
124                     os << _W("Redefining permanent variable.\n");
125                     throw ast::InternalError(os.str(), 999, e.getLeftExp().getLocation());
126                 }
127             }
128
129             if (e.isVerbose() && ConfigVariable::isPrintOutput())
130             {
131                 std::wstring wstrName = pVar->getSymbol().getName();
132                 std::wostringstream ostr;
133                 ostr << L" " << wstrName << L"  = " << std::endl << std::endl;
134                 scilabWriteW(ostr.str().c_str());
135                 std::wostringstream ostrName;
136                 ostrName << wstrName;
137                 VariableToString(pIT, ostrName.str().c_str());
138             }
139             CoverageInstance::stopChrono((void*)&e);
140             return;
141         }
142
143         if (e.getLeftExp().isCellCallExp())
144         {
145             CellCallExp *pCell = static_cast<CellCallExp*>(&e.getLeftExp());
146             types::InternalType *pOut = NULL;
147
148             /*getting what to assign*/
149             types::InternalType* pITR = e.getRightVal();
150             if (pITR == NULL)
151             {
152                 e.getRightExp().accept(*this);
153                 pITR = getResult();
154                 //reset result
155                 setResult(NULL);
156             }
157
158             if (pITR == NULL)
159             {
160                 // if the right hand is NULL.
161                 std::wostringstream os;
162                 os << _W("Unable to extract right part expression.\n");
163                 throw ast::InternalError(os.str(), 999, e.getLeftExp().getLocation());
164             }
165
166             std::list<ExpHistory*> fields;
167             if (getFieldsFromExp(pCell, fields) == false)
168             {
169                 for (std::list<ExpHistory*>::const_iterator i = fields.begin(), end = fields.end(); i != end; i++)
170                 {
171                     delete *i;
172                 }
173                 std::wostringstream os;
174                 os << _W("Get fields from expression failed.");
175                 throw ast::InternalError(os.str(), 999, e.getRightExp().getLocation());
176             }
177
178             try
179             {
180                 pOut = evaluateFields(pCell, fields, pITR);
181             }
182             catch (const InternalError& error)
183             {
184                 // catch error when call overload
185                 for (std::list<ExpHistory*>::const_iterator i = fields.begin(), end = fields.end(); i != end; i++)
186                 {
187                     (*i)->setDeleteCurrent(true);
188                     delete *i;
189                 }
190
191                 pITR->killMe();
192                 throw error;
193             }
194
195             for (std::list<ExpHistory*>::const_iterator i = fields.begin(), end = fields.end(); i != end; i++)
196             {
197                 delete *i;
198             }
199
200             pITR->killMe();
201
202             if (pOut == NULL)
203             {
204                 std::wostringstream os;
205                 os << _W("Fields evaluation failed.");
206                 throw ast::InternalError(os.str(), 999, e.getRightExp().getLocation());
207             }
208
209             if (pOut != NULL)
210             {
211                 if (e.isVerbose() && ConfigVariable::isPrintOutput())
212                 {
213                     std::wostringstream ostr;
214                     ostr << L" " << *getStructNameFromExp(pCell) << L"  = " << std::endl;
215                     ostr << std::endl;
216                     scilabWriteW(ostr.str().c_str());
217
218                     VariableToString(pOut, ostr.str().c_str());
219                 }
220             }
221             else
222             {
223                 //manage error
224                 std::wostringstream os;
225                 os << _W("Invalid Index.\n");
226                 throw ast::InternalError(os.str(), 999, e.getRightExp().getLocation());
227             }
228
229             CoverageInstance::stopChrono((void*)&e);
230             return;
231         }
232
233         if (e.getLeftExp().isCallExp())
234         {
235             CallExp *pCall = static_cast<CallExp*>(&e.getLeftExp());
236             //x(?) = ?
237             types::InternalType *pOut = NULL;
238
239             /*getting what to assign*/
240             types::InternalType* pITR = e.getRightVal();
241             if (pITR == NULL)
242             {
243                 e.getRightExp().accept(*this);
244                 pITR = getResult();
245                 //reset result
246                 setResult(NULL);
247             }
248
249             if (pITR == NULL)
250             {
251                 // if the right hand is NULL.
252                 std::wostringstream os;
253                 os << _W("Unable to extract right part expression.\n");
254                 throw ast::InternalError(os.str(), 999, e.getLeftExp().getLocation());
255             }
256
257             bool alreadyProcessed = false;
258             //a(...) without fields or whatever on arrayof derived types
259             if (pCall->getName().isSimpleVar())
260             {
261                 ast::SimpleVar* var = pCall->getName().getAs<ast::SimpleVar>();
262                 types::InternalType* pIT = ctx->getCurrentLevel(var->getStack());
263                 if (pIT && pIT->isArrayOf())
264                 {
265                     if (ctx->isprotected(var->getStack()))
266                     {
267                         std::wostringstream os;
268                         os << _W("Redefining permanent variable.\n");
269                         throw ast::InternalError(os.str(), 999, pCall->getLocation());
270                     }
271
272                     // prevent delete after extractFullMatrix
273                     // called in insertionCall when pITR is an ImplicitList
274                     pITR->IncreaseRef();
275
276                     types::typed_list* currentArgs = GetArgumentList(pCall->getArgs());
277
278                     try
279                     {
280                         pOut = insertionCall(e, currentArgs, pIT, pITR);
281                     }
282                     catch (const InternalError& error)
283                     {
284                         pITR->DecreaseRef();
285                         // call killMe on all arguments
286                         cleanOut(*currentArgs);
287                         delete currentArgs;
288                         // insertion have done, call killMe on pITR
289                         pITR->killMe();
290                         throw error;
291                     }
292
293                     pITR->DecreaseRef();
294
295                     // call killMe on all arguments
296                     cleanOut(*currentArgs);
297                     delete currentArgs;
298
299                     // insertion have done, call killMe on pITR
300                     pITR->killMe();
301
302                     if (pOut == NULL)
303                     {
304                         std::wostringstream os;
305                         os << _W("Submatrix incorrectly defined.\n");
306                         throw ast::InternalError(os.str(), 999, e.getLocation());
307                     }
308
309
310                     //update variable with new value
311                     if (pOut != pIT)
312                     {
313                         ctx->put(var->getStack(), pOut);
314                     }
315
316                     alreadyProcessed = true;
317                 }
318             }
319
320             if (alreadyProcessed == false)
321             {
322                 std::list<ExpHistory*> fields;
323                 if (getFieldsFromExp(pCall, fields) == false)
324                 {
325                     for (std::list<ExpHistory*>::const_iterator i = fields.begin(), end = fields.end(); i != end; i++)
326                     {
327                         delete *i;
328                     }
329
330                     std::wostringstream os;
331                     os << _W("Instruction left hand side: waiting for a name.");
332                     throw ast::InternalError(os.str(), 999, e.getRightExp().getLocation());
333                 }
334
335                 // prevent delete after extractFullMatrix
336                 // called in evaluateFields when pITR is an ImplicitList
337                 pITR->IncreaseRef();
338
339                 try
340                 {
341                     pOut = evaluateFields(pCall, fields, pITR);
342                 }
343                 catch (const InternalError& error)
344                 {
345                     // catch error when call overload
346                     for (std::list<ExpHistory*>::const_iterator i = fields.begin(), end = fields.end(); i != end; i++)
347                     {
348                         delete *i;
349                     }
350
351                     pITR->DecreaseRef();
352                     pITR->killMe();
353
354                     throw error;
355                 }
356
357                 for (std::list<ExpHistory*>::const_iterator i = fields.begin(), end = fields.end(); i != end; i++)
358                 {
359                     delete *i;
360                 }
361
362                 pITR->DecreaseRef();
363                 pITR->killMe();
364
365                 if (pOut == NULL)
366                 {
367                     std::wostringstream os;
368                     os << _W("Fields evaluation failed.");
369                     throw ast::InternalError(os.str(), 999, e.getRightExp().getLocation());
370                 }
371             }
372
373             if (e.isVerbose() && ConfigVariable::isPrintOutput())
374             {
375                 std::wostringstream ostr;
376                 ostr << L" " << *getStructNameFromExp(&pCall->getName()) << L"  = " << std::endl;
377                 ostr << std::endl;
378                 scilabWriteW(ostr.str().c_str());
379
380                 std::wostringstream ostrName;
381                 ostrName << *getStructNameFromExp(&pCall->getName());
382                 VariableToString(pOut, ostrName.str().c_str());
383             }
384
385             clearResult();
386             CoverageInstance::stopChrono((void*)&e);
387
388             return;
389         }
390
391         if (e.getLeftExp().isAssignListExp())
392         {
393             AssignListExp *pList = e.getLeftExp().getAs<AssignListExp>();
394             //[x,y] = ?
395             int iLhsCount = (int)pList->getExps().size();
396
397             /*getting what to assign*/
398             T exec;
399             exec.setExpectedSize(iLhsCount);
400             e.getRightExp().accept(exec);
401
402             if (exec.getResultSize() < iLhsCount)
403             {
404                 std::wostringstream os;
405                 os << _W("Incompatible assignation: trying to assign ") << exec.getResultSize();
406                 os << _W(" values in ") << iLhsCount << _W(" variables.") << std::endl;
407                 throw ast::InternalError(os.str(), 999, e.getRightExp().getLocation());
408             }
409
410             exps_t::const_reverse_iterator it;
411             exps_t exps = pList->getExps();
412             types::InternalType** pIT = new types::InternalType*[iLhsCount];
413             int i = 0;
414             for (i = iLhsCount - 1; i >= 0; i--)
415             {
416                 //create a new AssignExp and run it
417                 pIT[i] = exec.getResult(i);
418                 //protet rhs against removal [a,b] = (b,a);
419                 pIT[i]->IncreaseRef();
420             }
421
422             for (i = iLhsCount - 1, it = exps.rbegin(); it != exps.rend(); it++, i--)
423             {
424                 Exp* pExp = e.getRightExp().clone();
425                 AssignExp pAssign((*it)->getLocation(), *(*it), *pExp, pIT[i]);
426                 pAssign.setLrOwner(false);
427                 pAssign.setVerbose(e.isVerbose());
428                 pAssign.accept(*this);
429                 //clear result to take care of [n,n]
430                 exec.setResult(i, NULL);
431                 delete pExp;
432             }
433
434             for (i = iLhsCount - 1; i >= 0; i--)
435             {
436                 //unprotect rhs
437                 pIT[i]->DecreaseRef();
438                 pIT[i]->killMe();
439             }
440
441             delete[] pIT;
442             exec.clearResult();
443             CoverageInstance::stopChrono((void*)&e);
444             return;
445         }
446
447         if (e.getLeftExp().isFieldExp())
448         {
449             FieldExp *pField = static_cast<FieldExp*>(&e.getLeftExp());
450             types::InternalType *pIT = e.getRightVal();
451             if (pIT == NULL)
452             {
453                 //a.b = x
454                 //a.b can be a struct or a tlist/mlist or a handle
455                 /*getting what to assign*/
456                 setExpectedSize(1);
457                 e.getRightExp().accept(*this);
458                 pIT = getResult();
459                 setResult(NULL);
460             }
461
462             if (pIT->isImplicitList())
463             {
464                 if (pIT->getAs<types::ImplicitList>()->isComputable())
465                 {
466                     types::InternalType *pTemp = pIT->getAs<types::ImplicitList>()->extractFullMatrix();
467                     delete pIT;
468                     setResult(NULL);
469                     pIT = pTemp;
470                 }
471             }
472
473             std::list<ExpHistory*> fields;
474             if (getFieldsFromExp(pField, fields) == false)
475             {
476                 for (std::list<ExpHistory*>::const_iterator i = fields.begin(), end = fields.end(); i != end; i++)
477                 {
478                     delete *i;
479                 }
480                 std::wostringstream os;
481                 os << _W("Get fields from expression failed.");
482                 throw ast::InternalError(os.str(), 999, e.getRightExp().getLocation());
483             }
484
485             try
486             {
487                 if (evaluateFields(pField, fields, pIT) == NULL)
488                 {
489                     for (std::list<ExpHistory*>::const_iterator i = fields.begin(), end = fields.end(); i != end; i++)
490                     {
491                         delete *i;
492                     }
493                     std::wostringstream os;
494                     os << _W("Fields evaluation failed.");
495                     throw ast::InternalError(os.str(), 999, e.getRightExp().getLocation());
496                 }
497             }
498             catch (const InternalError& error)
499             {
500                 for (auto i : fields)
501                 {
502                     delete i;
503                 }
504
505                 throw error;
506             }
507
508             for (auto i : fields)
509             {
510                 delete i;
511             }
512
513             if (e.isVerbose() && ConfigVariable::isPrintOutput())
514             {
515                 const std::wstring *pstName = getStructNameFromExp(pField);
516
517                 types::InternalType* pPrint = ctx->get(symbol::Symbol(*pstName));
518                 std::wostringstream ostr;
519                 ostr << L" " << *pstName << L"  = " << std::endl << std::endl;
520                 scilabWriteW(ostr.str().c_str());
521
522                 std::wostringstream ostrName;
523                 ostrName << *pstName;
524                 VariableToString(pPrint, ostrName.str().c_str());
525             }
526
527             clearResult();
528             CoverageInstance::stopChrono((void*)&e);
529             return;
530         }
531
532         std::wostringstream os;
533         os << _W("unknown script form");
534         //os << ((Location)e.getRightExp().getLocation()).getLocationString() << std::endl;
535         throw ast::InternalError(os.str(), 999, e.getRightExp().getLocation());
536     }
537     catch (const InternalError& error)
538     {
539         CoverageInstance::stopChrono((void*)&e);
540         throw error;
541     }
542
543     CoverageInstance::stopChrono((void*)&e);
544 }
545
546 } /* namespace ast */