fix putInPreviousScope on libraries
[scilab.git] / scilab / modules / ast / includes / symbol / libraries.hxx
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2014 - Scilab Enterprises - Antoine ELIAS
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 __LIBRARIES_HXX__
14 #define __LIBRARIES_HXX__
15
16 #include <stack>
17 #include "symbol.hxx"
18 #include "types.hxx"
19 #include "library.hxx"
20
21 namespace symbol
22 {
23 struct ScopedLibrary
24 {
25     ScopedLibrary(int _iLevel, types::Library* _pLib) : m_iLevel(_iLevel), m_pLib(_pLib) {};
26
27     types::MacroFile* getMacroFile(const Symbol& _key)
28     {
29         return m_pLib->get(_key.getName());
30     }
31
32     int m_iLevel;
33     types::Library* m_pLib;
34 };
35
36 struct Library
37 {
38     typedef std::stack<ScopedLibrary*> StackLib;
39
40     Library(const Symbol& _name) : name(_name), m_global(false) {};
41
42     void put(types::Library* _pLib, int _iLevel)
43     {
44         if (empty() || top()->m_iLevel < _iLevel)
45         {
46             //create a new level
47             stack.push(new ScopedLibrary(_iLevel, _pLib));
48             _pLib->IncreaseRef();
49         }
50         else
51         {
52             //update current level
53             types::Library* pLib = top()->m_pLib;
54             if (pLib != _pLib)
55             {
56                 pLib->DecreaseRef();
57                 pLib->killMe();
58                 top()->m_pLib = _pLib;
59                 _pLib->IncreaseRef();
60             }
61         }
62     }
63
64     void put(ScopedLibrary* pSL)
65     {
66         stack.push(pSL);
67     }
68
69     types::MacroFile* get(const Symbol& _keyMacro) const
70     {
71         if (empty() == false)
72         {
73             return top()->getMacroFile(_keyMacro);
74         }
75
76         return NULL;
77     }
78
79     int getMacrosName(std::list<std::wstring>& lst)
80     {
81         if (empty() == false)
82         {
83             top()->m_pLib->getMacrosName(lst);
84         }
85
86         return static_cast<int>(lst.size());
87     }
88
89     bool empty() const
90     {
91         return stack.empty();
92     }
93
94     ScopedLibrary* top() const
95     {
96         return stack.top();
97     }
98
99     void pop()
100     {
101         stack.pop();
102     }
103
104     inline Symbol getSymbol() const
105     {
106         return name;
107     }
108
109 private :
110     StackLib stack;
111     Symbol name;
112     bool m_global;
113 };
114
115 struct Libraries
116 {
117     typedef std::map<Symbol, Library*> MapLibs;
118
119     Libraries() {};
120
121     Library* getOrCreate(const Symbol& _key)
122     {
123         MapLibs::const_iterator it = libs.find(_key);
124         if (it == libs.end())
125         {
126             //create an empty StackedValues
127             Library* lib = new Library(_key);
128             libs[_key] = lib;
129             return lib;
130         }
131
132         return it->second;
133     }
134
135     void put(const Symbol& _keyLib, types::Library* _pLib, int _iLevel)
136     {
137         Library* lib = getOrCreate(_keyLib);
138         lib->put(_pLib, _iLevel);
139     }
140
141     bool putInPreviousScope(const Symbol& _keyLib, types::Library* _pLib, int _iLevel)
142     {
143         Library* lib = getOrCreate(_keyLib);
144
145         if (lib->empty())
146         {
147             lib->put(_pLib, _iLevel);
148         }
149         else if (lib->top()->m_iLevel > _iLevel)
150         {
151             ScopedLibrary* pLib = lib->top();
152             lib->pop();
153             putInPreviousScope(_keyLib, _pLib, _iLevel);
154             //decresef ref before, increase it in put
155             //pVar->m_pIT->DecreaseRef();
156             lib->put(pLib->m_pLib, pLib->m_iLevel);
157         }
158         else
159         {
160             lib->put(_pLib, _iLevel);
161         }
162
163         return true;
164     }
165
166     types::InternalType* get(const Symbol& _key, int _iLevel)
167     {
168         //does _key is a lib name
169         auto lib = libs.find(_key);
170         if (lib != libs.end())
171         {
172             if (lib->second->empty() == false)
173             {
174                 if (_iLevel == -1 || lib->second->top()->m_iLevel == _iLevel)
175                 {
176                     return lib->second->top()->m_pLib;
177                 }
178             }
179         }
180
181         //does _key is a macro in a lib
182         auto it = libs.rbegin();
183         for (auto it = libs.rbegin(), itEnd = libs.rend(); it != itEnd ; ++it)
184         {
185             Library* lib = it->second;
186             if (it->second->empty() == false)
187             {
188                 if (_iLevel == -1 || it->second->top()->m_iLevel == _iLevel)
189                 {
190                     types::MacroFile* pMF = it->second->get(_key);
191                     if (pMF)
192                     {
193                         return (types::InternalType*)pMF;
194                     }
195                 }
196             }
197         }
198
199         return NULL;
200     }
201
202     bool remove(const Symbol& _key, int _iLevel)
203     {
204         MapLibs::iterator it = libs.find(_key);
205         if (it != libs.end())
206         {
207             if (it->second->empty() == false)
208             {
209                 if (it->second->top()->m_iLevel == _iLevel)
210                 {
211                     ScopedLibrary * pSL = it->second->top();
212                     types::Library* pIT = pSL->m_pLib;
213                     pIT->DecreaseRef();
214                     pIT->killMe();
215                     it->second->pop();
216                     delete pSL;
217                     return true;
218                 }
219             }
220         }
221
222         return false;
223     }
224
225     int getMacrosName(std::list<std::wstring>& lst)
226     {
227         MapLibs::iterator it = libs.begin();
228         MapLibs::iterator itEnd = libs.end();
229         for (auto it : libs)
230         {
231             it.second->getMacrosName(lst);
232         }
233
234         return static_cast<int>(lst.size());
235     }
236
237     int getVarsName(std::list<std::wstring>& lst)
238     {
239         for (auto it : libs)
240         {
241             if (it.second->empty() == false)
242             {
243                 lst.push_back(it.first.getName().c_str());
244             }
245         }
246
247         return static_cast<int>(lst.size());
248     }
249
250     int getVarsToVariableBrowser(std::list<Library*>& lst)
251     {
252         for (auto lib : libs)
253         {
254             if (lib.second->empty() == false)
255             {
256                 lst.push_back(lib.second);
257             }
258         }
259
260         return static_cast<int>(lst.size());
261     }
262
263     void clearAll()
264     {
265         for (auto lib : libs)
266         {
267             while (!lib.second->empty())
268             {
269                 ScopedLibrary * pSL = lib.second->top();
270                 types::InternalType * pIT = pSL->m_pLib;
271                 pIT->DecreaseRef();
272                 pIT->killMe();
273                 lib.second->pop();
274                 delete pSL;
275             }
276
277             delete lib.second;
278         }
279     }
280
281     bool getVarsNameForWho(std::list<std::wstring>* lstVarName, int* iVarLenMax, bool bSorted = false) const
282     {
283         for (auto it = libs.begin(), itEnd = libs.end(); it != itEnd; ++it)
284         {
285             std::wstring wstrVarName(it->first.getName().c_str());
286             if (lstVarName && it->second->empty() == false)
287             {
288                 lstVarName->push_back(wstrVarName);
289                 *iVarLenMax = std::max(*iVarLenMax, (int)wstrVarName.size());
290             }
291         }
292
293         if (bSorted)
294         {
295             if (lstVarName)
296             {
297                 lstVarName->sort();
298             }
299         }
300
301         return true;
302     }
303
304     int whereis(std::list<std::wstring>& lst, const Symbol& _key)
305     {
306         for (auto lib : libs)
307         {
308             if (lib.second->get(_key) != NULL)
309             {
310                 lst.push_back(lib.first.getName());
311             }
312         }
313         return static_cast<int>(lst.size());
314     }
315
316     int librarieslist(std::list<std::wstring>& lst)
317     {
318         for (auto lib : libs)
319         {
320             lst.push_back(lib.first.getName());
321         }
322
323         return static_cast<int>(lst.size());
324     }
325
326 private:
327     MapLibs libs;
328 };
329 }
330 #endif /* !__LIBRARIES_HXX__ */