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