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