09c17e16409646f35eb42ef16bef35782045dcca
[scilab.git] / scilab / modules / ast / src / cpp / symbol / context.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2008-2008 - DIGITEO - 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 #include "context.hxx"
13 #include "internal.hxx"
14 #include "function.hxx"
15 #include "macro.hxx"
16 #include "macrofile.hxx"
17 #include "variables.hxx"
18
19 namespace symbol
20 {
21 Context* Context::me;
22
23 Context::Context()
24 {
25     m_iLevel = 0;
26     varStack.push(new VarList());
27     globals = new std::list<Symbol>();
28 }
29
30 Context::~Context()
31 {
32     while (!varStack.empty())
33     {
34         VarList * pVL = varStack.top();
35         pVL->clear();
36         delete pVL;
37         varStack.pop();
38     }
39     if (globals)
40     {
41         delete globals;
42     }
43 }
44
45 Context* Context::getInstance(void)
46 {
47     if (me == 0)
48     {
49         me = new Context();
50     }
51     return me;
52 }
53
54 void Context::destroyInstance(void)
55 {
56     if (me)
57     {
58         delete me;
59     }
60 }
61
62 void Context::scope_begin()
63 {
64     m_iLevel++;
65     varStack.push(new VarList());
66 }
67
68 void Context::clearAll()
69 {
70     libraries.clearAll();
71     variables.clearAll();
72 }
73
74 void Context::scope_end()
75 {
76     //clear varList of current scope
77     if (varStack.empty() == false)
78     {
79         clearCurrentScope(true);
80     }
81
82     m_iLevel--;
83 }
84
85 bool Context::clearCurrentScope(bool _bClose)
86 {
87     if (varStack.empty())
88     {
89         return true;
90     }
91
92     VarList* varList = varStack.top();
93     std::map<Symbol, Variable*>::iterator it = varList->begin();
94     for (; it != varList->end() ; ++it)
95     {
96         if (it->second->empty() == false && it->second->top()->m_iLevel == m_iLevel)
97         {
98             ScopedVariable * pSV = it->second->top();
99             types::InternalType * pIT = pSV->m_pIT;
100             pIT->DecreaseRef();
101             pIT->killMe();
102             it->second->pop();
103             delete pSV;
104         }
105     }
106
107     varList->clear();
108
109     if (_bClose)
110     {
111         delete varList;
112         varStack.pop();
113     }
114
115     return true;
116 }
117
118 Variable* Context::getOrCreate(const Symbol& _key)
119 {
120     return variables.getOrCreate(_key);
121 }
122
123 types::InternalType* Context::get(const Symbol& _key)
124 {
125     return get(_key, -1);
126 }
127
128 types::InternalType* Context::get(const Variable* _var)
129 {
130     types::InternalType* pIT = _var->get();
131
132     if (pIT == NULL)
133     {
134         //look in libraries
135         pIT = libraries.get(_var->getSymbol(), -1);
136         if (pIT)
137         {
138             put((Variable*)_var, pIT);
139         }
140     }
141
142     return pIT;
143 }
144
145 types::InternalType* Context::get(const Symbol& _key, int _iLevel)
146 {
147     types::InternalType* pIT = NULL;
148     if (_iLevel == m_iLevel || _iLevel == -1)
149     {
150         //look for in current VarList
151         VarList::iterator it = varStack.top()->find(_key);
152         if (it != varStack.top()->end())
153         {
154             if (it->second->empty() == false)
155             {
156                 return it->second->top()->m_pIT;
157             }
158         }
159     }
160
161     if (pIT == NULL)
162     {
163         pIT = variables.get(_key, _iLevel);
164         if (pIT == NULL)
165         {
166             //find in libraries
167             pIT = libraries.get(_key, _iLevel);
168             if (pIT)
169             {
170                 //add symbol to current scope
171                 put(_key, pIT);
172             }
173         }
174     }
175
176     return pIT;
177 }
178
179 types::InternalType* Context::getCurrentLevel(const Symbol& _key)
180 {
181     return variables.get(_key, m_iLevel);
182 }
183
184 types::InternalType* Context::getAllButCurrentLevel(const Symbol& _key)
185 {
186     return variables.getAllButCurrentLevel(_key, m_iLevel);
187 }
188
189 types::InternalType* Context::getFunction(const Symbol& _key)
190 {
191     return get(_key);
192 }
193
194 std::list<Symbol>* Context::getFunctionList(std::wstring _stModuleName)
195 {
196     return variables.getFunctionList(_stModuleName, m_iLevel);
197 }
198
199 std::list<std::wstring>* Context::getVarsName()
200 {
201     return variables.getVarsName();
202 }
203
204 std::list<std::wstring>* Context::getMacrosName()
205 {
206     std::list<std::wstring>* vars = variables.getMacrosName();
207     std::list<std::wstring>* libs = libraries.getMacrosName();
208     vars->insert(vars->end(), libs->begin(), libs->end());
209     delete libs;
210     return vars;
211 }
212
213 std::list<std::wstring>* Context::getFunctionsName()
214 {
215     return variables.getFunctionsName();
216 }
217
218 void Context::put(Variable* _var, types::InternalType* _pIT)
219 {
220     _var->put(_pIT, m_iLevel);
221     if (varStack.empty() == false)
222     {
223         (*varStack.top())[_var->getSymbol()] = _var;
224     }
225
226     if (_pIT->isLibrary())
227     {
228         Library* lib = libraries.getOrCreate(_var->getSymbol());
229         lib->put((types::Library*)_pIT, m_iLevel);
230     }
231 }
232
233 void Context::put(const Symbol& _key, types::InternalType* _pIT)
234 {
235     Variable* var = variables.getOrCreate(_key);
236     put(var, _pIT);
237 }
238
239 bool Context::remove(const Symbol& _key)
240 {
241     if (variables.remove(_key, m_iLevel))
242     {
243         varStack.top()->erase(_key);
244         libraries.remove(_key, m_iLevel);
245         return true;
246     }
247
248     return false;
249 }
250
251 bool Context::removeAll()
252 {
253     return clearCurrentScope(false);
254 }
255
256 bool Context::putInPreviousScope(Variable* _var, types::InternalType* _pIT)
257 {
258     //add variable in previous scope
259     variables.putInPreviousScope(_var, _pIT, m_iLevel - 1);
260
261     //add variable in stack of using variables
262     if (varStack.empty() == false)
263     {
264         VarList * list = varStack.top();
265         varStack.pop();
266         if (varStack.empty() == false)
267         {
268             (*varStack.top())[_var->getSymbol()] = _var;
269             varStack.push(list);
270         }
271     }
272     return true;
273 }
274
275 bool Context::addFunction(types::Function *_info)
276 {
277     Variable* var = variables.getOrCreate(Symbol(_info->getName()));
278     variables.putInPreviousScope(var, _info, 0);
279     return true;
280 }
281
282 bool Context::addMacro(types::Macro *_info)
283 {
284     put(Symbol(_info->getName()), _info);
285     return true;
286 }
287
288 bool Context::addMacroFile(types::MacroFile *_info)
289 {
290     put(Symbol(_info->getName()), _info);
291     return true;
292 }
293
294 bool Context::isGlobalVisible(const Symbol& _key)
295 {
296     return variables.isGlobalVisible(_key, m_iLevel);
297 }
298
299 /*return global variable existance status*/
300 bool Context::isGlobal(const Symbol& _key)
301 {
302     return variables.isGlobal(_key, m_iLevel);
303 }
304
305 types::InternalType* Context::getGlobalValue(const Symbol& _key)
306 {
307     return variables.getGlobalValue(_key);
308 }
309
310 void Context::setGlobalVisible(const Symbol& _key, bool bVisible)
311 {
312     variables.setGlobalVisible(_key, bVisible, m_iLevel);
313 }
314
315 void Context::setGlobal(const Symbol& _key)
316 {
317     variables.setGlobal(_key);
318     globals->push_back(_key);
319 }
320
321 void Context::removeGlobal(const Symbol& _key)
322 {
323     variables.removeGlobal(_key, m_iLevel);
324 }
325
326 void Context::removeGlobalAll()
327 {
328     std::list<Symbol>::iterator it = globals->begin();
329     for (; it != globals->end(); ++it)
330     {
331         removeGlobal(*it);
332     }
333
334     globals->clear();
335 }
336
337 void Context::print(std::wostream& ostr) const
338 {
339     ostr << L"  Environment Variables:" << std::endl;
340     ostr << L"==========================" << std::endl;
341 }
342
343 }