Analysis: fix bug in listexp when in a vardec
[scilab.git] / scilab / modules / ast / src / cpp / analysis / FunctionBlock.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2014 - Scilab Enterprises - Calixte DENIZET
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 "debugvisitor.hxx"
14 #include "printvisitor.hxx"
15
16 #include "data/DataManager.hxx"
17 #include "data/FunctionBlock.hxx"
18 #include "data/CompleteMacroSignature.hxx"
19 #include "gvn/ConstraintManager.hxx"
20
21 namespace analysis
22 {
23
24 FunctionBlock::FunctionBlock(const unsigned int id, Block * parent, ast::Exp * exp) : Block(id, parent, exp), loopAnalyzer(exp), constraintManager(*this, dm->topFunction())
25 {
26     gvn = &fgvn;
27     dm->pushFunction(this);
28     //std::wcerr << L"Loop analyze:" << loopAnalyzer << std::endl;
29 }
30
31 bool FunctionBlock::addIn(const TITypeSignatureTuple & tuple, const std::vector<GVN::Value *> & values)
32 {
33     std::vector<TITypeSignature>::const_iterator i = tuple.types.begin();
34     for (const auto & sym : in)
35     {
36         Info & info = addSym(sym, new Data(false, sym));
37         info.type = TIType(fgvn, i->type, i->scalar);
38         dm->registerData(info.data);//, __LINE__, __FILE__);
39         ++i;
40     }
41
42     for (const auto & sym : globals)
43     {
44         Info & info = addSym(sym, new Data(false, sym));
45         info.type = TIType(fgvn, i->type, i->scalar);
46         dm->registerData(info.data);//, __LINE__, __FILE__);
47         ++i;
48     }
49     inValues = values;
50     maxVarId = fgvn.getCurrentValue() - 1;
51
52     return true;
53 }
54
55 void FunctionBlock::addGlobal(const symbol::Symbol & sym)
56 {
57     //globals.emplace(sym);
58     Block::addGlobal(sym);
59 }
60
61 void FunctionBlock::setGlobals(const tools::SymbolOrdSet & v)
62 {
63     //globals = v; => bug on mac
64     std::copy(v.begin(), v.end(), std::inserter(globals, globals.begin()));
65 }
66
67 /*    TITypeSignatureTuple FunctionBlock::getGlobals(std::vector<symbol::Symbol> & v)
68     {
69         TITypeSignatureTuple tuple;
70         std::vector<TITypeSignature> & t = tuple.types;
71         t.reserve(globals.size());
72         v.reserve(globals.size());
73
74         for (const auto & sym : globals)
75         {
76             v.emplace_back(sym);
77             tools::SymbolMap<Info>::iterator it;
78             Block * block = parent->getDefBlock(sym, it);
79             if (block)
80             {
81                 t.emplace_back(it->second.type.type, it->second.type.isscalar());
82             }
83             else
84             {
85                 bool exists;
86                 TIType ty = DataManager::getSymInScilabContext(fgvn, sym, exists);
87                 t.emplace_back(ty.type, ty.isscalar());
88             }
89         }
90
91         return tuple;
92     }
93 */
94 MacroOut FunctionBlock::getOuts()
95 {
96     MacroOut mo;
97     mo.maxVarId = maxVarId;
98     std::vector<TIType> & v = mo.tuple.types;
99     v.reserve(lhs);
100     unsigned int i = 0;
101     for (std::vector<symbol::Symbol>::const_iterator s = out.begin(); i < lhs; ++i, ++s)
102     {
103         tools::SymbolMap<Info>::iterator it;
104         Block * block = getDefBlock(*s, it, false);
105         if (block == this)
106         {
107             v.emplace_back(it->second.type);
108         }
109         else
110         {
111             addGlobal(*s);
112             if (block)
113             {
114                 v.emplace_back(it->second.type);
115             }
116             else
117             {
118                 // TODO: if exists is false then it is an error
119                 bool exists;
120                 v.emplace_back(DataManager::getSymInScilabContext(fgvn, *s, exists));
121             }
122         }
123     }
124
125     return mo;
126 }
127
128 void FunctionBlock::finalize()
129 {
130     dm->popFunction();
131
132     for (unsigned int i = 0; i != lhs; ++i)
133     {
134         auto it = symMap.find(out[i]);
135         if (it != symMap.end())
136         {
137             const TIType & type = it->second.type;
138             if (type.isscalar())
139             {
140                 types_out.emplace_back(out[i], TypeLocal(type.type, 1, 1, false));
141             }
142             else
143             {
144                 types_out.emplace_back(out[i], TypeLocal(type.type, -1, -1, false));
145             }
146         }
147         else
148         {
149             types_out.emplace_back(out[i], TypeLocal(TIType::UNKNOWN, -1, -1, false));
150         }
151
152         auto jt = locals.find(out[i]);
153         if (jt != locals.end())
154         {
155             jt->second.erase(types_out.back().second);
156             if (jt->second.empty())
157             {
158                 locals.erase(jt);
159             }
160         }
161     }
162 }
163
164 void FunctionBlock::addLocal(const symbol::Symbol & sym, const TIType & type, const bool isAnInt)
165 {
166     auto i = locals.find(sym);
167     if (i == locals.end())
168     {
169         i = locals.emplace(sym, std::set<TypeLocal>()).first;
170     }
171
172     i->second.emplace(TypeLocal::get(type, isAnInt));
173 }
174
175 int FunctionBlock::getTmpId(const TIType & type, const bool isAnInt)
176 {
177     return tempManager.getTmp(type, isAnInt);
178 }
179
180 void FunctionBlock::releaseTmp(const int id)
181 {
182     tempManager.releaseTmp(id);
183 }
184
185 void FunctionBlock::setInOut(MacroDef * macrodef, const unsigned int rhs, const std::vector<TIType> & _in)
186 {
187     in = macrodef->getIn();
188     out = macrodef->getOut();
189
190     for (unsigned int i = 0; i != rhs; ++i)
191     {
192         if (_in[i].isscalar())
193         {
194             types_in.emplace_back(in[i], TypeLocal(_in[i].type, 1, 1, false));
195         }
196         else
197         {
198             types_in.emplace_back(in[i], TypeLocal(_in[i].type, -1, -1, false));
199         }
200     }
201 }
202
203 Block * FunctionBlock::getDefBlock(const symbol::Symbol & sym, tools::SymbolMap<Info>::iterator & it, const bool global)
204 {
205     it = symMap.find(sym);
206     if (it == symMap.end())
207     {
208         if (!global && globals.find(sym) == globals.end())
209         {
210             // we have looked for a symbol which is not in this function
211             // so we add it and give it an unknown type
212             it = symMap.emplace(sym, new Data(false, sym)).first;
213             Info & info = it->second;
214             info.local = Info::Local::INFO_UNKNOWN;
215             info.type = TIType(fgvn);
216             dm->registerData(info.data);
217         }
218         else
219         {
220             return parent->getDefBlock(sym, it, true);
221         }
222     }
223     return this;
224 }
225
226 std::wostream & operator<<(std::wostream & out, const FunctionBlock & fblock)
227 {
228     out << L"Function " << fblock.name << L'\n'
229         << L" -LHS: " << fblock.lhs << L'\n'
230         << L" -RHS: " << fblock.rhs << L'\n'
231         << L" -in:" << L'\n';
232     for (const auto & p : fblock.types_in)
233     {
234         out << L"   -" << p.first << L" -> " << p.second << L'\n';
235     }
236
237     out << L'\n'
238         << L" -out:" << L'\n';
239     for (const auto & p : fblock.types_out)
240     {
241         out << L"   -" << p.first << L" -> " << p.second << L'\n';
242     }
243     out << L'\n';
244     if (fblock.locals.empty())
245     {
246         out << L" -locals: none" << L'\n';
247     }
248     else
249     {
250         out << L" -locals:" << L'\n';
251         for (const auto & p : fblock.locals)
252         {
253             out << L"   -" << p.first << L" -> ";
254             tools::printSet(p.second, out);
255             out << L'\n';
256         }
257     }
258
259     out << L'\n';
260     const std::map<TypeLocal, std::stack<int>> & temps = fblock.getTemp();
261     if (temps.empty())
262     {
263         out << L" -temps: none" << L'\n';
264     }
265     else
266     {
267         out << L" -temps:" << L'\n';
268         for (const auto & p : temps)
269         {
270             out << L"   -" << p.first << L" -> " << p.second.size() << L'\n';
271         }
272     }
273
274     //ast::PrintVisitor pv(out, true, false);
275     //fblock.exp->accept(pv);
276
277     ast::DebugVisitor dv(out);
278     fblock.exp->accept(dv);
279
280     return out;
281 }
282 }