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