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