c925bce42868d9eca5371d336f418c41b1e72f57
[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) {}
28
29     int m_iLevel;
30     bool m_globalVisible;
31     types::InternalType* m_pIT;
32 };
33
34 struct Variable
35 {
36     Variable(const Symbol& _name) : name(_name), m_Global(false), m_GlobalValue(NULL) {};
37     ~Variable()
38     {
39         while (!empty())
40         {
41             ScopedVariable * pSV = top();
42             types::InternalType * pIT = pSV->m_pIT;
43             pIT->DecreaseRef();
44             pIT->killMe();
45             pop();
46             delete pSV;
47         }
48
49         if (m_GlobalValue)
50         {
51             m_GlobalValue->DecreaseRef();
52             m_GlobalValue->killMe();
53         }
54     }
55
56     void put(types::InternalType* _pIT, int _iLevel)
57     {
58         if (isGlobal() && isGlobalVisible(_iLevel))
59         {
60             setGlobalValue(_pIT);
61             return;
62         }
63
64         if (empty() || top()->m_iLevel < _iLevel)
65         {
66             //create a new level
67             stack.push(new ScopedVariable(_iLevel, _pIT));
68             _pIT->IncreaseRef();
69         }
70         else
71         {
72             //update current level
73             types::InternalType* pIT = top()->m_pIT;
74             if (pIT != _pIT)
75             {
76                 // _pIT may contained in pIT
77                 // so increases ref of _pIT before kill pIT
78                 top()->m_pIT = _pIT;
79                 _pIT->IncreaseRef();
80                 pIT->DecreaseRef();
81                 pIT->killMe();
82             }
83         }
84     }
85
86     inline types::InternalType* get() const
87     {
88         if (empty())
89         {
90             return NULL;
91         }
92
93         if (m_Global && top()->m_globalVisible)
94         {
95             return m_GlobalValue;
96         }
97         else
98         {
99             return top()->m_pIT;
100         }
101     }
102
103     inline bool empty() const
104     {
105         return stack.empty();
106     }
107
108     inline ScopedVariable* top() const
109     {
110         return stack.top();
111     }
112
113     inline void pop()
114     {
115         stack.pop();
116     }
117
118     inline Symbol name_get() const
119     {
120         return name;
121     }
122
123     //globals
124
125     inline void setGlobal(bool _bGlobal)
126     {
127         m_Global = _bGlobal;
128     }
129
130     inline bool isGlobal()
131     {
132         return m_Global;
133     }
134
135     inline bool isGlobalVisible(int _iLevel)
136     {
137         if (empty() == false)
138         {
139             if (top()->m_iLevel == _iLevel)
140             {
141                 return top()->m_globalVisible;
142             }
143         }
144
145         return false;
146     }
147
148     void setGlobalVisible(int _iLevel, bool _bVisible)
149     {
150         if (empty() || top()->m_iLevel != _iLevel)
151         {
152             stack.push(new ScopedVariable(_iLevel, types::Double::Empty()));
153         }
154
155
156         top()->m_globalVisible = _bVisible;
157     }
158
159     void setGlobalValue(types::InternalType* _pIT)
160     {
161         if (m_GlobalValue != _pIT)
162         {
163             if (m_GlobalValue)
164             {
165                 m_GlobalValue->DecreaseRef();
166                 m_GlobalValue->killMe();
167             }
168
169             m_GlobalValue = _pIT;
170             if (_pIT != NULL)
171             {
172                 _pIT->IncreaseRef();
173             }
174         }
175     }
176
177     inline types::InternalType* getGlobalValue()
178     {
179         return m_GlobalValue;
180     }
181
182 private :
183     Symbol name;
184     types::InternalType* m_GlobalValue;
185     bool m_Global;
186     typedef std::stack<ScopedVariable*> StackVar;
187     StackVar stack;
188 };
189
190 struct Variables
191 {
192     Variables() {};
193
194     Variable* getOrCreate(const Symbol& _key)
195     {
196         MapVars::const_iterator it = vars.find(_key);
197         if (it == vars.end())
198         {
199             //create an empty StackedValues
200             Variable* var = new Variable(_key);
201             vars[_key] = var;
202             return var;
203         }
204
205         return it->second;
206     }
207
208     void put(const Symbol& _key, types::InternalType* _pIT, int _iLevel)
209     {
210         Variable* var = getOrCreate(_key);
211         var->put(_pIT, _iLevel);
212     }
213
214     types::InternalType* get(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 (_iLevel == -1 || it->second->top()->m_iLevel == _iLevel)
220             {
221                 return it->second->get();
222             }
223         }
224
225         return NULL;
226     }
227
228     types::InternalType* get(Variable* _var, int _iLevel)
229     {
230         if (_var != NULL && _var->empty() == false)
231         {
232             if (_iLevel == -1 || _var->top()->m_iLevel == _iLevel)
233             {
234                 return _var->get();
235             }
236         }
237
238         return NULL;
239     }
240
241     types::InternalType* getAllButCurrentLevel(const Symbol& _key, int _iLevel)
242     {
243         MapVars::const_iterator it = vars.find(_key);
244         if (it != vars.end() && it->second->empty() == false)
245         {
246             if (it->second->top()->m_iLevel < _iLevel)
247             {
248                 return it->second->get();
249             }
250             else
251             {
252                 ScopedVariable* pSave = it->second->top();
253                 it->second->pop();
254                 types::InternalType* pIT = getAllButCurrentLevel(_key, _iLevel);
255                 it->second->put(pSave->m_pIT, pSave->m_iLevel);
256                 delete pSave;
257                 return pIT;
258             }
259         }
260
261         return NULL;
262     }
263
264     bool remove(Variable* _var, int _iLevel)
265     {
266         if (_var->empty() == false)
267         {
268             if (_var->top()->m_iLevel == _iLevel)
269             {
270                 ScopedVariable* pSave = _var->top();
271                 types::InternalType* pIT = pSave->m_pIT;
272                 pIT->DecreaseRef();
273                 pIT->killMe();
274                 _var->pop();
275                 delete pSave;
276             }
277         }
278
279         return true;
280     }
281
282     bool remove(const Symbol& _key, int _iLevel)
283     {
284         MapVars::iterator it = vars.find(_key);
285         if (it != vars.end())
286         {
287             Variable* pVar = it->second;
288             return remove(pVar, _iLevel);
289         }
290
291         return false;
292     }
293
294     std::list<std::wstring>* getMacrosName()
295     {
296         std::list<std::wstring>* plOut = new std::list<std::wstring>();
297         MapVars::const_iterator it = vars.begin();
298         for (; it != vars.end(); ++it)
299         {
300             if (it->second->empty() == false)
301             {
302                 types::InternalType* pIT = it->second->top()->m_pIT;
303                 if (pIT && (pIT->isMacro() || pIT->isMacroFile()))
304                 {
305                     plOut->push_back(it->first.name_get().c_str());
306                 }
307             }
308         }
309
310         return plOut;
311     }
312
313     std::list<std::wstring>* getVarsName()
314     {
315         std::list<std::wstring>* plOut = new std::list<std::wstring>();
316         MapVars::const_iterator it = vars.begin();
317         for (; it != vars.end(); ++it)
318         {
319             if (it->second->empty() == false)
320             {
321                 types::InternalType* pIT = it->second->top()->m_pIT;
322                 if (pIT &&
323                         pIT->isMacro() == false &&
324                         pIT->isMacroFile() == false &&
325                         pIT->isFunction() == false)
326                 {
327                     plOut->push_back(it->first.name_get().c_str());
328                 }
329             }
330         }
331
332         return plOut;
333     }
334
335     std::list<std::wstring>* getFunctionsName()
336     {
337         std::list<std::wstring>* plOut = new std::list<std::wstring>();
338         MapVars::const_iterator it = vars.begin();
339         for (; it != vars.end(); ++it)
340         {
341             if (it->second->empty() == false)
342             {
343                 types::InternalType* pIT = it->second->top()->m_pIT;
344                 if (pIT && pIT->isFunction())
345                 {
346                     plOut->push_back(it->first.name_get().c_str());
347                 }
348             }
349         }
350
351         return plOut;
352     }
353
354     std::list<Symbol>* getFunctionList(std::wstring _stModuleName, int _iLevel)
355     {
356         std::list<Symbol>* symb = new std::list<Symbol>();
357
358         MapVars::iterator it = vars.begin();
359         for (; it != vars.end() ; ++it)
360         {
361             if (it->second->empty())
362             {
363                 continue;
364             }
365
366             if ((it->second->top()->m_iLevel == _iLevel || _iLevel == 1) && it->second->top()->m_pIT->isCallable())
367             {
368                 types::Callable* pCall = it->second->top()->m_pIT->getAs<types::Callable>();
369                 if (_stModuleName == L"" || _stModuleName == pCall->getModule())
370                 {
371                     symb->push_back(it->first);
372                 }
373             }
374         }
375
376         return symb;
377     }
378
379     bool putInPreviousScope(Variable* _var, types::InternalType* _pIT, int _iLevel)
380     {
381         if (_var->empty())
382         {
383             _var->put(_pIT, _iLevel);
384         }
385         else if (_var->top()->m_iLevel > _iLevel)
386         {
387             ScopedVariable* pVar = _var->top();
388             _var->pop();
389             putInPreviousScope(_var, _pIT, _iLevel);
390             _var->put(pVar->m_pIT, pVar->m_iLevel);
391             delete pVar;
392         }
393         else
394         {
395             _var->put(_pIT, _iLevel);
396         }
397
398         return true;
399     }
400
401     //globals
402
403     void setGlobal(const Symbol& _key)
404     {
405         getOrCreate(_key)->setGlobal(true);
406     }
407
408     void setGlobalVisible(const Symbol& _key, bool _bVisible, int _iLevel)
409     {
410         Variable* pVar = getOrCreate(_key);
411         pVar->setGlobalVisible(_iLevel, _bVisible);
412         if (_bVisible)
413         {
414             pVar->setGlobal(true);
415         }
416     }
417
418     bool isGlobalVisible(const Symbol& _key, int _iLevel)
419     {
420         return getOrCreate(_key)->isGlobalVisible(_iLevel);
421     }
422
423     bool isGlobal(const Symbol& _key, int _iLevel)
424     {
425         return getOrCreate(_key)->isGlobal();
426     }
427
428     types::InternalType* getGlobalValue(const Symbol& _key)
429     {
430         return getOrCreate(_key)->getGlobalValue();
431     }
432
433     void removeGlobal(const Symbol& _key, int _iLevel)
434     {
435         Variable* pVar = getOrCreate(_key);
436         if (pVar->isGlobal())
437         {
438             pVar->setGlobal(false);
439             pVar->setGlobalValue(NULL);
440         }
441
442         remove(pVar, _iLevel);
443     }
444
445     void clearAll()
446     {
447         for (MapVars::iterator it = vars.begin(); it != vars.end() ; ++it)
448         {
449             delete it->second;
450         }
451     }
452
453 private:
454     typedef std::map<Symbol, Variable*> MapVars;
455     MapVars vars;
456 };
457 }
458
459 #endif // !__VARIABLES_HXX__