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