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