d83addd6534ccae8296c29d69ce129d4a78a6f84
[scilab.git] / scilab / modules / ast / src / cpp / symbol / variables.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2015 - Scilab Enterprises - 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 <algorithm>
17 #include "variables.hxx"
18 #include "configvariable.hxx"
19 #include "macro.hxx"
20 #include "macrofile.hxx"
21
22 extern "C"
23 {
24 #include "sciprint.h"
25 }
26
27 namespace symbol
28 {
29 Variable::~Variable()
30 {
31     while (!empty())
32     {
33         ScopedVariable * pSV = top();
34         types::InternalType * pIT = pSV->m_pIT;
35         pIT->DecreaseRef();
36         pIT->killMe();
37         pop();
38         delete pSV;
39     }
40
41     if (m_GlobalValue)
42     {
43         m_GlobalValue->DecreaseRef();
44         m_GlobalValue->killMe();
45     }
46 }
47
48 void Variable::setGlobalValue(types::InternalType* _pIT)
49 {
50     if (m_GlobalValue != _pIT)
51     {
52         if (m_GlobalValue)
53         {
54             m_GlobalValue->DecreaseRef();
55             m_GlobalValue->killMe();
56         }
57
58         m_GlobalValue = _pIT;
59         if (_pIT != NULL)
60         {
61             _pIT->IncreaseRef();
62         }
63     }
64 }
65
66 void Variable::setGlobalVisible(int _iLevel, bool _bVisible)
67 {
68     if (empty() || top()->m_iLevel != _iLevel)
69     {
70         last = new ScopedVariable(_iLevel, types::Double::Empty());
71         stack.push(last);
72     }
73
74     top()->m_globalVisible = _bVisible;
75 }
76
77
78 bool Variable::put(types::InternalType* _pIT, int _iLevel)
79 {
80     if (isGlobal() && isGlobalVisible(_iLevel))
81     {
82         setGlobalValue(_pIT);
83         return true;
84     }
85
86     if (empty() || top()->m_iLevel < _iLevel)
87     {
88         //create a new level
89         last = new ScopedVariable(_iLevel, _pIT);
90         stack.push(last);
91         _pIT->IncreaseRef();
92     }
93     else
94     {
95         //update current level
96         types::InternalType* pIT = top()->m_pIT;
97         if (pIT != _pIT)
98         {
99             //check macro redefinition
100             if (_pIT->isMacro())
101             {
102                 int iFuncProt = ConfigVariable::getFuncprot();
103                 if (iFuncProt != 0)
104                 {
105                     bool bEquals = true;
106                     if (pIT && pIT->isCallable())
107                     {
108                         if (pIT->isMacroFile())
109                         {
110                             types::MacroFile* pMF = pIT->getAs<types::MacroFile>();
111                             bEquals = *pMF->getMacro() == *_pIT;
112                         }
113                         else if (pIT->isMacro())
114                         {
115                             types::Macro* pM = pIT->getAs<types::Macro>();
116                             bEquals = *pM == *_pIT;
117                         }
118                     }
119
120                     if (bEquals == false)
121                     {
122                         if (iFuncProt == 2)
123                         {
124                             return false;
125                         }
126
127                         if (ConfigVariable::getWarningMode())
128                         {
129                             wchar_t pwstFuncName[1024];
130                             os_swprintf(pwstFuncName, 1024, L"%-24ls", name.getName().c_str());
131                             char* pstFuncName = wide_string_to_UTF8(pwstFuncName);
132
133                             sciprint(_("Warning : redefining function: %s. Use funcprot(0) to avoid this message"), pstFuncName);
134                             sciprint("\n");
135                             FREE(pstFuncName);
136                         }
137                     }
138                 }
139             }
140
141             // _pIT may contained in pIT
142             // so increases ref of _pIT before kill pIT
143             top()->m_pIT = _pIT;
144             if (pIT)
145             {
146                 _pIT->IncreaseRef();
147                 pIT->DecreaseRef();
148                 pIT->killMe();
149             }
150         }
151     }
152
153     return true;
154 }
155
156 Variable* Variables::getOrCreate(const Symbol& _key)
157 {
158     MapVars::const_iterator it = vars.find(_key);
159     if (it == vars.end())
160     {
161         //create an empty StackedValues
162         Variable* var = new Variable(_key);
163         vars[_key] = var;
164         return var;
165     }
166
167     return it->second;
168 }
169
170 int Variables::getLevel(const Symbol& _key) const
171 {
172     MapVars::const_iterator it = vars.find(_key);
173     if (it != vars.end() && !it->second->empty())
174     {
175         return it->second->top()->m_iLevel;
176     }
177
178     return SCOPE_ALL;
179 }
180
181 void Variables::put(const Symbol& _key, types::InternalType* _pIT, int _iLevel)
182 {
183     Variable* var = getOrCreate(_key);
184     var->put(_pIT, _iLevel);
185 }
186
187 types::InternalType* Variables::get(const Symbol& _key, int _iLevel)
188 {
189     MapVars::const_iterator it = vars.find(_key);
190     if (it != vars.end() && it->second->empty() == false)
191     {
192         if (_iLevel == SCOPE_ALL || it->second->top()->m_iLevel == _iLevel)
193         {
194             return it->second->get();
195         }
196     }
197
198     return NULL;
199 }
200
201 types::InternalType* Variables::get(Variable* _var, int _iLevel)
202 {
203     if (_var != NULL && _var->empty() == false)
204     {
205         if (_iLevel == SCOPE_ALL || _var->top()->m_iLevel == _iLevel)
206         {
207             return _var->get();
208         }
209     }
210
211     return NULL;
212 }
213
214 types::InternalType* Variables::getAllButCurrentLevel(const Symbol& _key, int _iLevel)
215 {
216     MapVars::const_iterator it = vars.find(_key);
217     if (it != vars.end() && it->second->empty() == false)
218     {
219         if (it->second->top()->m_iLevel < _iLevel)
220         {
221             return it->second->get();
222         }
223         else
224         {
225             ScopedVariable* pSave = it->second->top();
226             it->second->pop();
227             types::InternalType* pIT = getAllButCurrentLevel(_key, _iLevel);
228             it->second->put(pSave);
229             return pIT;
230         }
231     }
232
233     return NULL;
234 }
235
236 bool Variables::remove(Variable* _var, int _iLevel)
237 {
238     if (_var->empty() == false)
239     {
240         if (_var->top()->m_iLevel == _iLevel)
241         {
242             ScopedVariable* pSave = _var->top();
243             types::InternalType* pIT = pSave->m_pIT;
244             pIT->DecreaseRef();
245             pIT->killMe();
246             _var->pop();
247             delete pSave;
248             return true;
249         }
250     }
251
252     return false;
253 }
254
255 bool Variables::remove(const Symbol& _key, int _iLevel)
256 {
257     MapVars::iterator it = vars.find(_key);
258     if (it != vars.end())
259     {
260         Variable* pVar = it->second;
261         return remove(pVar, _iLevel);
262     }
263
264     return false;
265 }
266
267 int Variables::getMacrosName(std::list<std::wstring>& lst)
268 {
269     for (auto it : vars)
270     {
271         if (it.second->empty() == false)
272         {
273             types::InternalType* pIT = it.second->top()->m_pIT;
274             if (pIT && (pIT->isMacro() || pIT->isMacroFile()))
275             {
276                 lst.push_back(it.first.getName().c_str());
277             }
278         }
279     }
280
281     return static_cast<int>(lst.size());
282 }
283
284 int Variables::getVarsName(std::list<std::wstring>& lst)
285 {
286     for (auto it : vars)
287     {
288         if (it.second->empty() == false)
289         {
290             types::InternalType* pIT = it.second->top()->m_pIT;
291             if (pIT &&
292                     pIT->isMacro() == false &&
293                     pIT->isMacroFile() == false &&
294                     pIT->isFunction() == false)
295             {
296                 lst.push_back(it.first.getName().c_str());
297             }
298         }
299     }
300
301     return static_cast<int>(lst.size());
302 }
303
304 bool Variables::getVarsNameForWho(std::list<std::wstring>& lstVarName, int* iVarLenMax, bool bSorted) const
305 {
306     for (auto it : vars)
307     {
308         std::wstring wstrVarName(it.first.getName().c_str());
309         if (it.second->empty() == false)
310         {
311             types::InternalType* pIT = it.second->top()->m_pIT;
312             if (pIT && pIT->isFunction() == false)
313             {
314                 lstVarName.push_back(wstrVarName);
315                 *iVarLenMax = std::max(*iVarLenMax, (int)wstrVarName.size());
316             }
317         }
318     }
319
320     if (bSorted)
321     {
322         lstVarName.sort();
323     }
324
325     return true;
326 }
327
328 bool Variables::getGlobalNameForWho(std::list<std::wstring>& lstVarName, int* iVarLenMax, bool bSorted) const
329 {
330     for (auto it : vars)
331     {
332         if (it.second->isGlobal())
333         {
334             std::wstring wstrVarName(it.first.getName().c_str());
335             lstVarName.push_back(wstrVarName);
336             *iVarLenMax = std::max(*iVarLenMax, (int)wstrVarName.size());
337         }
338     }
339
340     if (bSorted)
341     {
342         lstVarName.sort();
343     }
344
345     return true;
346 }
347
348 int Variables::getProtectedVarsName(std::list<std::wstring>& lstVarName) const
349 {
350     for (auto it : vars)
351     {
352         if (it.second->empty() == false)
353         {
354             ScopedVariable* pSV = it.second->top();
355             if (pSV->protect && it.first.getName() != L"ans")
356             {
357                 lstVarName.push_back(it.first.getName());
358             }
359         }
360     }
361
362     return static_cast<int>(lstVarName.size());
363 }
364
365 int Variables::getFunctionsName(std::list<std::wstring>& lst)
366 {
367     for (auto it : vars)
368     {
369         if (it.second->empty() == false)
370         {
371             types::InternalType* pIT = it.second->top()->m_pIT;
372             if (pIT && pIT->isFunction())
373             {
374                 lst.push_back(it.first.getName().c_str());
375             }
376         }
377     }
378
379     return static_cast<int>(lst.size());
380 }
381
382 int Variables::getFunctionList(std::list<Symbol>& lst, std::wstring _stModuleName, int _iLevel)
383 {
384     for (auto var : vars)
385     {
386         if (var.second->empty())
387         {
388             continue;
389         }
390
391         if ((var.second->top()->m_iLevel == _iLevel || _iLevel == 1) && var.second->top()->m_pIT->isCallable())
392         {
393             types::Callable* pCall = var.second->top()->m_pIT->getAs<types::Callable>();
394             if (_stModuleName == L"" || _stModuleName == pCall->getModule())
395             {
396                 lst.push_back(var.first);
397             }
398         }
399     }
400
401     return static_cast<int>(lst.size());
402 }
403
404 int Variables::getFunctionList(std::list<types::Callable *>& lst, std::wstring _stModuleName, int _iLevel)
405 {
406     for (auto var : vars)
407     {
408         if (var.second->empty())
409         {
410             continue;
411         }
412
413         if ((var.second->top()->m_iLevel == _iLevel || _iLevel == 1) && var.second->top()->m_pIT->isCallable())
414         {
415             types::Callable * pCall = var.second->top()->m_pIT->getAs<types::Callable>();
416             if (_stModuleName == L"" || _stModuleName == pCall->getModule())
417             {
418                 lst.push_back(pCall);
419             }
420         }
421     }
422
423     return static_cast<int>(lst.size());
424 }
425
426 int Variables::getVarsToVariableBrowser(std::list<Variable*>& lst)
427 {
428     for (auto var : vars)
429     {
430         if (var.second->empty() == false)
431         {
432             types::InternalType* pIT = var.second->top()->m_pIT;
433             if (pIT &&
434                     pIT->isMacro() == false &&
435                     pIT->isMacroFile() == false &&
436                     pIT->isFunction() == false)
437             {
438                 lst.push_back(var.second);
439             }
440         }
441     }
442
443     return static_cast<int>(lst.size());
444 }
445
446 bool Variables::putInPreviousScope(Variable* _var, types::InternalType* _pIT, int _iLevel)
447 {
448     if (_var->empty())
449     {
450         return _var->put(_pIT, _iLevel);
451     }
452     else if (_var->top()->m_iLevel > _iLevel)
453     {
454         ScopedVariable* pVar = _var->top();
455         _var->pop();
456         if (putInPreviousScope(_var, _pIT, _iLevel) == false)
457         {
458             return false;
459         }
460         //decresef ref before, increase it in put
461         //pVar->m_pIT->DecreaseRef();
462         return _var->put(pVar);
463     }
464     else
465     {
466         if (_var->top()->protect == false)
467         {
468             return _var->put(_pIT, _iLevel);
469         }
470     }
471
472     return false;
473 }
474
475 //globals
476
477 void Variables::setGlobal(const Symbol& _key)
478 {
479     getOrCreate(_key)->setGlobal(true);
480 }
481
482 void Variables::setGlobalVisible(const Symbol& _key, bool _bVisible, int _iLevel)
483 {
484     Variable* pVar = getOrCreate(_key);
485     pVar->setGlobalVisible(_iLevel, _bVisible);
486     if (_bVisible)
487     {
488         pVar->setGlobal(true);
489     }
490 }
491
492 bool Variables::isGlobalVisible(const Symbol& _key, int _iLevel)
493 {
494     return getOrCreate(_key)->isGlobalVisible(_iLevel);
495 }
496
497 bool Variables::isGlobal(const Symbol& _key, int /*_iLevel*/)
498 {
499     return getOrCreate(_key)->isGlobal();
500 }
501
502 types::InternalType* Variables::getGlobalValue(const Symbol& _key)
503 {
504     return getOrCreate(_key)->getGlobalValue();
505 }
506
507 void Variables::removeGlobal(const Symbol& _key, int _iLevel)
508 {
509     Variable* pVar = getOrCreate(_key);
510     if (pVar->isGlobal())
511     {
512         pVar->setGlobal(false);
513         pVar->setGlobalValue(NULL);
514     }
515
516     remove(pVar, _iLevel);
517 }
518
519 void Variables::clearAll()
520 {
521     for (auto var : vars)
522     {
523         delete var.second;
524     }
525
526     vars.clear();
527 }
528
529
530 }