258d79a4b9d734daf37785e2926cabd633c7ed8e
[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     int getLevel(const Symbol& _key) const
229     {
230         MapVars::const_iterator it = vars.find(_key);
231         if (it != vars.end() && !it->second->empty())
232         {
233             return it->second->top()->m_iLevel;
234         }
235
236         return SCOPE_ALL;
237     }
238
239     void put(const Symbol& _key, types::InternalType* _pIT, int _iLevel)
240     {
241         Variable* var = getOrCreate(_key);
242         var->put(_pIT, _iLevel);
243     }
244
245     types::InternalType* get(const Symbol& _key, int _iLevel)
246     {
247         MapVars::const_iterator it = vars.find(_key);
248         if (it != vars.end() && it->second->empty() == false)
249         {
250             if (_iLevel == SCOPE_ALL || it->second->top()->m_iLevel == _iLevel)
251             {
252                 return it->second->get();
253             }
254         }
255
256         return NULL;
257     }
258
259     types::InternalType* get(Variable* _var, int _iLevel)
260     {
261         if (_var != NULL && _var->empty() == false)
262         {
263             if (_iLevel == SCOPE_ALL || _var->top()->m_iLevel == _iLevel)
264             {
265                 return _var->get();
266             }
267         }
268
269         return NULL;
270     }
271
272     types::InternalType* getAllButCurrentLevel(const Symbol& _key, int _iLevel)
273     {
274         MapVars::const_iterator it = vars.find(_key);
275         if (it != vars.end() && it->second->empty() == false)
276         {
277             if (it->second->top()->m_iLevel < _iLevel)
278             {
279                 return it->second->get();
280             }
281             else
282             {
283                 ScopedVariable* pSave = it->second->top();
284                 it->second->pop();
285                 types::InternalType* pIT = getAllButCurrentLevel(_key, _iLevel);
286                 it->second->put(pSave);
287                 return pIT;
288             }
289         }
290
291         return NULL;
292     }
293
294     bool remove(Variable* _var, int _iLevel)
295     {
296         if (_var->empty() == false)
297         {
298             if (_var->top()->m_iLevel == _iLevel)
299             {
300                 ScopedVariable* pSave = _var->top();
301                 types::InternalType* pIT = pSave->m_pIT;
302                 pIT->DecreaseRef();
303                 pIT->killMe();
304                 _var->pop();
305                 delete pSave;
306                 return true;
307             }
308         }
309
310         return false;
311     }
312
313     bool remove(const Symbol& _key, int _iLevel)
314     {
315         MapVars::iterator it = vars.find(_key);
316         if (it != vars.end())
317         {
318             Variable* pVar = it->second;
319             return remove(pVar, _iLevel);
320         }
321
322         return false;
323     }
324
325     int getMacrosName(std::list<std::wstring>& lst)
326     {
327         for (auto it : vars)
328         {
329             if (it.second->empty() == false)
330             {
331                 types::InternalType* pIT = it.second->top()->m_pIT;
332                 if (pIT && (pIT->isMacro() || pIT->isMacroFile()))
333                 {
334                     lst.push_back(it.first.getName().c_str());
335                 }
336             }
337         }
338
339         return static_cast<int>(lst.size());
340     }
341
342     int getVarsName(std::list<std::wstring>& lst)
343     {
344         for (auto it : vars)
345         {
346             if (it.second->empty() == false)
347             {
348                 types::InternalType* pIT = it.second->top()->m_pIT;
349                 if (pIT &&
350                         pIT->isMacro() == false &&
351                         pIT->isMacroFile() == false &&
352                         pIT->isFunction() == false)
353                 {
354                     lst.push_back(it.first.getName().c_str());
355                 }
356             }
357         }
358
359         return static_cast<int>(lst.size());
360     }
361
362     bool getVarsNameForWho(std::list<std::wstring>& lstVarName, int* iVarLenMax, bool bSorted = false) const
363     {
364         for (auto it : vars)
365         {
366             std::wstring wstrVarName(it.first.getName().c_str());
367             if (it.second->empty() == false)
368             {
369                 types::InternalType* pIT = it.second->top()->m_pIT;
370                 if (pIT && pIT->isFunction() == false)
371                 {
372                     lstVarName.push_back(wstrVarName);
373                     *iVarLenMax = std::max(*iVarLenMax, (int)wstrVarName.size());
374                 }
375             }
376         }
377
378         if (bSorted)
379         {
380             lstVarName.sort();
381         }
382
383         return true;
384     }
385
386     bool getGlobalNameForWho(std::list<std::wstring>& lstVarName, int* iVarLenMax, bool bSorted = false) const
387     {
388         for (auto it : vars)
389         {
390             if (it.second->empty() == false && it.second->isGlobal())
391             {
392                 std::wstring wstrVarName(it.first.getName().c_str());
393                 lstVarName.push_back(wstrVarName);
394                 *iVarLenMax = std::max(*iVarLenMax, (int)wstrVarName.size());
395             }
396         }
397
398         if (bSorted)
399         {
400             lstVarName.sort();
401         }
402
403         return true;
404     }
405
406     int getProtectedVarsName(std::list<std::wstring>& lstVarName) const
407     {
408         for (auto it : vars)
409         {
410             if (it.second->empty() == false)
411             {
412                 ScopedVariable* pSV = it.second->top();
413                 if (pSV->protect && it.first.getName() != L"ans")
414                 {
415                     lstVarName.push_back(it.first.getName());
416                 }
417             }
418         }
419
420         return static_cast<int>(lstVarName.size());
421     }
422
423     int getFunctionsName(std::list<std::wstring>& lst)
424     {
425         for (auto it : vars)
426         {
427             if (it.second->empty() == false)
428             {
429                 types::InternalType* pIT = it.second->top()->m_pIT;
430                 if (pIT && pIT->isFunction())
431                 {
432                     lst.push_back(it.first.getName().c_str());
433                 }
434             }
435         }
436
437         return static_cast<int>(lst.size());
438     }
439
440     int getFunctionList(std::list<Symbol>& lst, std::wstring _stModuleName, int _iLevel)
441     {
442         for (auto var : vars)
443         {
444             if (var.second->empty())
445             {
446                 continue;
447             }
448
449             if ((var.second->top()->m_iLevel == _iLevel || _iLevel == 1) && var.second->top()->m_pIT->isCallable())
450             {
451                 types::Callable* pCall = var.second->top()->m_pIT->getAs<types::Callable>();
452                 if (_stModuleName == L"" || _stModuleName == pCall->getModule())
453                 {
454                     lst.push_back(var.first);
455                 }
456             }
457         }
458
459         return static_cast<int>(lst.size());
460     }
461
462     int getVarsToVariableBrowser(std::list<Variable*>& lst)
463     {
464         for (auto var : vars)
465         {
466             if (var.second->empty() == false)
467             {
468                 types::InternalType* pIT = var.second->top()->m_pIT;
469                 if (pIT &&
470                         pIT->isMacro() == false &&
471                         pIT->isMacroFile() == false &&
472                         pIT->isFunction() == false)
473                 {
474                     lst.push_back(var.second);
475                 }
476             }
477         }
478
479         return static_cast<int>(lst.size());
480     }
481
482     bool putInPreviousScope(Variable* _var, types::InternalType* _pIT, int _iLevel)
483     {
484         if (_var->empty())
485         {
486             _var->put(_pIT, _iLevel);
487         }
488         else if (_var->top()->m_iLevel > _iLevel)
489         {
490             ScopedVariable* pVar = _var->top();
491             _var->pop();
492             putInPreviousScope(_var, _pIT, _iLevel);
493             //decresef ref before, increase it in put
494             //pVar->m_pIT->DecreaseRef();
495             _var->put(pVar);
496         }
497         else
498         {
499             _var->put(_pIT, _iLevel);
500         }
501
502         return true;
503     }
504
505     //globals
506
507     void setGlobal(const Symbol& _key)
508     {
509         getOrCreate(_key)->setGlobal(true);
510     }
511
512     void setGlobalVisible(const Symbol& _key, bool _bVisible, int _iLevel)
513     {
514         Variable* pVar = getOrCreate(_key);
515         pVar->setGlobalVisible(_iLevel, _bVisible);
516         if (_bVisible)
517         {
518             pVar->setGlobal(true);
519         }
520     }
521
522     bool isGlobalVisible(const Symbol& _key, int _iLevel)
523     {
524         return getOrCreate(_key)->isGlobalVisible(_iLevel);
525     }
526
527     bool isGlobal(const Symbol& _key, int /*_iLevel*/)
528     {
529         return getOrCreate(_key)->isGlobal();
530     }
531
532     types::InternalType* getGlobalValue(const Symbol& _key)
533     {
534         return getOrCreate(_key)->getGlobalValue();
535     }
536
537     void removeGlobal(const Symbol& _key, int _iLevel)
538     {
539         Variable* pVar = getOrCreate(_key);
540         if (pVar->isGlobal())
541         {
542             pVar->setGlobal(false);
543             pVar->setGlobalValue(NULL);
544         }
545
546         remove(pVar, _iLevel);
547     }
548
549     void clearAll()
550     {
551         for (auto var : vars)
552         {
553             delete var.second;
554         }
555
556         vars.clear();
557     }
558
559 private:
560     MapVars vars;
561 };
562 }
563
564 #endif // !__VARIABLES_HXX__