5df413ca85e23de4eab1df9f861c5be1b38eb8e9
[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 nullptr;
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     int getLevel(const Symbol& _key) const
136     {
137         MapLibs::const_iterator it = libs.find(_key);
138         if (it != libs.end())
139         {
140             if (!it->second->empty())
141             {
142                 return it->second->top()->m_iLevel;
143             }
144         }
145         else
146         {
147             for (auto i = libs.rbegin(), end = libs.rend(); i != end; ++i)
148             {
149                 Library * lib = i->second;
150                 if (!lib->empty())
151                 {
152                     types::MacroFile * pMF = lib->get(_key);
153                     if (pMF)
154                     {
155                         return lib->top()->m_iLevel;
156                     }
157                 }
158             }
159         }
160
161         return SCOPE_ALL;
162     }
163
164     void put(const Symbol& _keyLib, types::Library* _pLib, int _iLevel)
165     {
166         Library* lib = getOrCreate(_keyLib);
167         lib->put(_pLib, _iLevel);
168     }
169
170     bool putInPreviousScope(const Symbol& _keyLib, types::Library* _pLib, int _iLevel)
171     {
172         Library* lib = getOrCreate(_keyLib);
173
174         if (lib->empty())
175         {
176             lib->put(_pLib, _iLevel);
177         }
178         else if (lib->top()->m_iLevel > _iLevel)
179         {
180             ScopedLibrary* pLib = lib->top();
181             lib->pop();
182             putInPreviousScope(_keyLib, _pLib, _iLevel);
183             //decresef ref before, increase it in put
184             //pVar->m_pIT->DecreaseRef();
185             lib->put(pLib->m_pLib, pLib->m_iLevel);
186         }
187         else
188         {
189             lib->put(_pLib, _iLevel);
190         }
191
192         return true;
193     }
194
195     types::InternalType* get(const Symbol& _key, int _iLevel)
196     {
197         //does _key is a lib name
198         auto lib = libs.find(_key);
199         if (lib != libs.end())
200         {
201             if (lib->second->empty() == false)
202             {
203                 if (_iLevel == SCOPE_ALL || lib->second->top()->m_iLevel == _iLevel)
204                 {
205                     return lib->second->top()->m_pLib;
206                 }
207             }
208         }
209
210         //does _key is a macro in a lib
211         auto it = libs.rbegin();
212         for (auto it = libs.rbegin(), itEnd = libs.rend(); it != itEnd ; ++it)
213         {
214             Library* lib = it->second;
215             if (it->second->empty() == false)
216             {
217                 if (_iLevel == SCOPE_ALL || it->second->top()->m_iLevel == _iLevel)
218                 {
219                     types::MacroFile* pMF = it->second->get(_key);
220                     if (pMF)
221                     {
222                         return (types::InternalType*)pMF;
223                     }
224                 }
225             }
226         }
227
228         return NULL;
229     }
230
231     bool remove(const Symbol& _key, int _iLevel)
232     {
233         MapLibs::iterator it = libs.find(_key);
234         if (it != libs.end())
235         {
236             if (it->second->empty() == false)
237             {
238                 if (it->second->top()->m_iLevel == _iLevel)
239                 {
240                     ScopedLibrary * pSL = it->second->top();
241                     types::Library* pIT = pSL->m_pLib;
242                     pIT->DecreaseRef();
243                     pIT->killMe();
244                     it->second->pop();
245                     delete pSL;
246                     return true;
247                 }
248             }
249         }
250
251         return false;
252     }
253
254     int getMacrosName(std::list<std::wstring>& lst)
255     {
256         MapLibs::iterator it = libs.begin();
257         MapLibs::iterator itEnd = libs.end();
258         for (auto it : libs)
259         {
260             it.second->getMacrosName(lst);
261         }
262
263         return static_cast<int>(lst.size());
264     }
265
266     int getVarsName(std::list<std::wstring>& lst)
267     {
268         for (auto it : libs)
269         {
270             if (it.second->empty() == false)
271             {
272                 lst.push_back(it.first.getName().c_str());
273             }
274         }
275
276         return static_cast<int>(lst.size());
277     }
278
279     int getVarsToVariableBrowser(std::list<Library*>& lst)
280     {
281         for (auto lib : libs)
282         {
283             if (lib.second->empty() == false)
284             {
285                 lst.push_back(lib.second);
286             }
287         }
288
289         return static_cast<int>(lst.size());
290     }
291
292     void clearAll()
293     {
294         for (auto lib : libs)
295         {
296             while (!lib.second->empty())
297             {
298                 ScopedLibrary * pSL = lib.second->top();
299                 types::InternalType * pIT = pSL->m_pLib;
300                 pIT->DecreaseRef();
301                 pIT->killMe();
302                 lib.second->pop();
303                 delete pSL;
304             }
305
306             delete lib.second;
307         }
308     }
309
310     bool getVarsNameForWho(std::list<std::wstring>* lstVarName, int* iVarLenMax, bool bSorted = false) const
311     {
312         for (auto it = libs.begin(), itEnd = libs.end(); it != itEnd; ++it)
313         {
314             std::wstring wstrVarName(it->first.getName().c_str());
315             if (lstVarName && it->second->empty() == false)
316             {
317                 lstVarName->push_back(wstrVarName);
318                 *iVarLenMax = std::max(*iVarLenMax, (int)wstrVarName.size());
319             }
320         }
321
322         if (bSorted)
323         {
324             if (lstVarName)
325             {
326                 lstVarName->sort();
327             }
328         }
329
330         return true;
331     }
332
333     int whereis(std::list<std::wstring>& lst, const Symbol& _key)
334     {
335         for (auto lib : libs)
336         {
337             if (lib.second->get(_key) != NULL)
338             {
339                 lst.push_back(lib.first.getName());
340             }
341         }
342         return static_cast<int>(lst.size());
343     }
344
345     int librarieslist(std::list<std::wstring>& lst)
346     {
347         for (auto lib : libs)
348         {
349             lst.push_back(lib.first.getName());
350         }
351
352         return static_cast<int>(lst.size());
353     }
354
355 private:
356     MapLibs libs;
357 };
358 }
359 #endif /* !__LIBRARIES_HXX__ */