e8b4564d3e7857899250c14b8287b5ae5fbb2145
[scilab.git] / scilab / modules / ast / src / cpp / analysis / ConstantVisitor.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2015 - 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 "AnalysisVisitor.hxx"
14 #include "ConstantVisitor.hxx"
15
16 namespace analysis
17 {
18
19 std::unordered_set<std::wstring> ConstantVisitor::constants = init();
20
21 void ConstantVisitor::visit(ast::SimpleVar & e)
22 {
23     bool isConstant = false;
24     if (evalSymbols)
25     {
26         const symbol::Symbol & sym = e.getSymbol();
27         const std::wstring & name = sym.getName();
28         if (constants.find(name) != constants.end() && symbol::Context::getInstance()->isOriginalSymbol(sym))
29         {
30             if (types::InternalType * pIT = symbol::Context::getInstance()->get(sym))
31             {
32                 e.replace(pIT->getExp(e.getLocation()));
33                 isConstant = true;
34             }
35         }
36         else if (parent)
37         {
38             if (FunctionBlock * fblock = parent->getDM().topFunction())
39             {
40                 ast::Exp * loop = parent->getCurrentLoop();
41                 if (!fblock->getLoopAnalyzer().isAssigned(loop, sym))
42                 {
43                     // We propagate the constant only if we aren't in a loop which modifies the sym
44                     Info & info = parent->getDM().read(sym, &e);
45                     ConstantValue & constant = info.getConstant();
46                     const ConstantValue::Kind kind = constant.getKind();
47                     if (kind == ConstantValue::GVNVAL)
48                     {
49                         double val;
50                         if (constant.getDblValue(val))
51                         {
52                             e.replace(new ast::DoubleExp(e.getLocation(), val));
53                             isConstant = true;
54                         }
55                     }
56                     else if (kind == ConstantValue::ITVAL)
57                     {
58                         types::InternalType * pIT = constant.getIT();
59                         if (ast::Exp * exp = pIT->getExp(e.getLocation()))
60                         {
61                             e.replace(exp);
62                             isConstant = true;
63                         }
64                     }
65                 }
66             }
67         }
68     }
69
70     setResult(isConstant);
71 }
72
73 void ConstantVisitor::visit(ast::OpExp & e)
74 {
75     e.getLeft().accept(*this);
76     const bool constL = getResult();
77     e.getRight().accept(*this);
78     const bool constR = getResult();
79
80     if (constL && constR)
81     {
82         setResult(execAndReplace(e));
83         return;
84     }
85     else if (constL || constR)
86     {
87         const ast::Exp::ExpType ty = e.getParent()->getType();
88         if (ty == ast::Exp::IFEXP || ty == ast::Exp::WHILEEXP)
89         {
90             ast::OpExp::Oper oper = e.getOper();
91             if (oper == ast::OpExp::Oper::logicalShortCutAnd || oper == ast::OpExp::Oper::logicalAnd)
92             {
93                 if (constL)
94                 {
95                     e.getLeft().accept(exec);
96                     if (exec.getResult()->isTrue())
97                     {
98                         e.replace(e.getRight().clone());
99                     }
100                     else
101                     {
102                         types::InternalType * b = new types::Bool(0);
103                         e.replace(b->getExp(e.getLocation()));
104                         setResult(true);
105                         return;
106                     }
107                 }
108                 else
109                 {
110                     e.getRight().accept(exec);
111                     if (exec.getResult()->isTrue())
112                     {
113                         e.replace(e.getLeft().clone());
114                     }
115                     else
116                     {
117                         types::InternalType * b = new types::Bool(0);
118                         e.replace(b->getExp(e.getLocation()));
119                         setResult(true);
120                         return;
121                     }
122                 }
123             }
124             else if (oper == ast::OpExp::Oper::logicalShortCutOr || oper == ast::OpExp::Oper::logicalOr)
125             {
126                 if (constL)
127                 {
128                     e.getLeft().accept(exec);
129                     if (exec.getResult()->isTrue())
130                     {
131                         types::InternalType * b = new types::Bool(1);
132                         e.replace(b->getExp(e.getLocation()));
133                         setResult(true);
134                         return;
135                     }
136                     else
137                     {
138                         e.replace(e.getRight().clone());
139                     }
140                 }
141                 else
142                 {
143                     e.getRight().accept(exec);
144                     if (exec.getResult()->isTrue())
145                     {
146                         types::InternalType * b = new types::Bool(1);
147                         e.replace(b->getExp(e.getLocation()));
148                         setResult(true);
149                         return;
150                     }
151                     else
152                     {
153                         e.replace(e.getLeft().clone());
154                     }
155                 }
156             }
157         }
158     }
159
160     setResult(false);
161 }
162
163 void ConstantVisitor::visit(ast::LogicalOpExp & e)
164 {
165     visit(static_cast<ast::OpExp &>(e));
166 }
167
168 void ConstantVisitor::visit(ast::CallExp & e)
169 {
170     bool isConstant = false;
171
172     if (evalSymbols)
173     {
174         ast::SimpleVar & var = static_cast<ast::SimpleVar &>(e.getName());
175         const symbol::Symbol & sym = var.getSymbol();
176         if (symbol::Context::getInstance()->isOriginalSymbol(sym))
177         {
178             const std::wstring & name = sym.getName();
179             ast::exps_t args = e.getArgs();
180
181             bool allConstant = true;
182             for (auto arg : args)
183             {
184                 arg->accept(*this);
185                 if (allConstant && !getResult())
186                 {
187                     allConstant = false;
188                 }
189             }
190
191             if (allConstant && Checkers::isConst(name, args.size()))
192             {
193                 if (name == L"argn")
194                 {
195                     if (parent && parent->getAnalyzer(sym)->analyze(*parent, lhs, e))
196                     {
197                         if (lhs == 1)
198                         {
199                             double val;
200                             parent->getResult().getConstant().getDblValue(val);
201                             e.replace(new ast::DoubleExp(e.getLocation(), val));
202                             isConstant = true;
203                         }
204                         else
205                         {
206                             double val;
207                             ast::exps_t exps;
208                             exps.reserve(2);
209                             std::vector<Result> & res = parent->getLHSContainer();
210                             res.front().getConstant().getDblValue(val);
211                             exps.push_back(new ast::DoubleExp(e.getLocation(), val));
212                             res.back().getConstant().getDblValue(val);
213                             exps.push_back(new ast::DoubleExp(e.getLocation(), val));
214                             e.replace(new ast::ArrayListExp(e.getLocation(), exps));
215                             isConstant = true;
216                         }
217                     }
218                 }
219                 else
220                 {
221                     isConstant = execAndReplace(e);
222                 }
223             }
224
225             if (parent && args.size() == 1)
226             {
227                 if (name == L"type" || name == L"inttype")
228                 {
229                     if (parent->getAnalyzer(sym)->analyze(*parent, 1, e))
230                     {
231                         double val;
232                         parent->getResult().getConstant().getDblValue(val);
233                         e.replace(new ast::DoubleExp(e.getLocation(), val));
234                         isConstant = true;
235                     }
236                 }
237                 else if (name == L"typeof")
238                 {
239                     if (parent->getAnalyzer(sym)->analyze(*parent, 1, e))
240                     {
241                         std::wstring wstr;
242                         if (parent->getResult().getConstant().getStrValue(wstr))
243                         {
244                             e.replace(new ast::StringExp(e.getLocation(), wstr));
245                             isConstant = true;
246                         }
247                     }
248                 }
249                 else if (name == L"isreal" || name == L"isscalar")
250                 {
251                     if (parent->getAnalyzer(sym)->analyze(*parent, 1, e))
252                     {
253                         bool val;
254                         parent->getResult().getConstant().getBoolValue(val);
255                         e.replace(new ast::BoolExp(e.getLocation(), val));
256                         isConstant = true;
257                     }
258                 }
259             }
260         }
261     }
262
263     setResult(isConstant);
264 }
265
266 void ConstantVisitor::visit(ast::MatrixExp & e)
267 {
268     const ast::exps_t & lines = e.getLines();
269     if (lines.empty())
270     {
271         setResult(execAndReplace(e));
272     }
273     else
274     {
275         for (auto line : lines)
276         {
277             const ast::exps_t & columns = static_cast<ast::MatrixLineExp *>(line)->getColumns();
278             for (auto column : columns)
279             {
280                 column->accept(*this);
281                 if (!getResult())
282                 {
283                     return;
284                 }
285             }
286         }
287         setResult(execAndReplace(e));
288     }
289 }
290
291 void ConstantVisitor::visit(ast::NotExp & e)
292 {
293     e.getExp().accept(*this);
294     if (getResult())
295     {
296         setResult(execAndReplace(e));
297     }
298     else
299     {
300         setResult(false);
301     }
302 }
303
304 void ConstantVisitor::visit(ast::TransposeExp & e)
305 {
306     e.getExp().accept(*this);
307     if (getResult())
308     {
309         setResult(execAndReplace(e));
310     }
311     else
312     {
313         setResult(false);
314     }
315 }
316
317 void ConstantVisitor::visit(ast::CellExp & e)
318 {
319     visit(static_cast<ast::MatrixExp &>(e));
320 }
321
322 void ConstantVisitor::visit(ast::ListExp & e)
323 {
324     e.getStart().accept(*this);
325     const bool startConst = getResult();
326     e.getStep().accept(*this);
327     const bool stepConst = getResult();
328     e.getEnd().accept(*this);
329     const bool endConst = getResult();
330
331     if (startConst && stepConst && endConst)
332     {
333         setResult(execAndReplace(e));
334     }
335     else
336     {
337         setResult(false);
338     }
339 }
340
341 void ConstantVisitor::visit(ast::IfExp & e)
342 {
343 }
344
345 void ConstantVisitor::visit(ast::DollarVar & e)
346 {
347     setResult(false);
348 }
349
350 void ConstantVisitor::visit(ast::ColonVar & e)
351 {
352     setResult(false);
353 }
354
355 void ConstantVisitor::visit(ast::ArrayListVar & e)
356 {
357 }
358
359 void ConstantVisitor::visit(ast::DoubleExp & e)
360 {
361     setResult(true);
362 }
363
364 void ConstantVisitor::visit(ast::BoolExp & e)
365 {
366     setResult(true);
367 }
368
369 void ConstantVisitor::visit(ast::StringExp & e)
370 {
371     setResult(true);
372 }
373
374 void ConstantVisitor::visit(ast::CommentExp & e)
375 {
376     // ignored
377 }
378
379 void ConstantVisitor::visit(ast::NilExp & e)
380 {
381     // nothing to do
382 }
383
384 void ConstantVisitor::visit(ast::CellCallExp & e)
385 {
386     setResult(false);
387 }
388
389 void ConstantVisitor::visit(ast::AssignExp & e)
390 {
391 }
392
393 void ConstantVisitor::visit(ast::WhileExp & e)
394 {
395 }
396
397 void ConstantVisitor::visit(ast::ForExp & e)
398 {
399 }
400
401 void ConstantVisitor::visit(ast::BreakExp & e)
402 {
403     // nothing to do
404 }
405
406 void ConstantVisitor::visit(ast::ContinueExp & e)
407 {
408     // nothing to do
409 }
410
411 void ConstantVisitor::visit(ast::TryCatchExp & e)
412 {
413 }
414
415 void ConstantVisitor::visit(ast::SelectExp & e)
416 {
417 }
418
419 void ConstantVisitor::visit(ast::CaseExp & e)
420 {
421 }
422
423 void ConstantVisitor::visit(ast::ReturnExp & e)
424 {
425 }
426
427 void ConstantVisitor::visit(ast::FieldExp & e)
428 {
429 }
430
431 void ConstantVisitor::visit(ast::MatrixLineExp & e)
432 {
433 }
434
435 void ConstantVisitor::visit(ast::SeqExp & e)
436 {
437 }
438
439 void ConstantVisitor::visit(ast::ArrayListExp & e)
440 {
441 }
442
443 void ConstantVisitor::visit(ast::AssignListExp & e)
444 {
445 }
446
447 void ConstantVisitor::visit(ast::VarDec & e)
448 {
449 }
450
451 void ConstantVisitor::visit(ast::FunctionDec & e)
452 {
453 }
454
455 void ConstantVisitor::visit(ast::OptimizedExp & e)
456 {
457 }
458
459 void ConstantVisitor::visit(ast::MemfillExp & e)
460 {
461 }
462
463 void ConstantVisitor::visit(ast::DAXPYExp & e)
464 {
465 }
466
467 void ConstantVisitor::visit(ast::IntSelectExp & e)
468 {
469 }
470
471 void ConstantVisitor::visit(ast::StringSelectExp & e)
472 {
473 }
474
475 std::unordered_set<std::wstring> ConstantVisitor::init()
476 {
477     std::unordered_set<std::wstring> _constants;
478     _constants.emplace(L"%pi");
479     _constants.emplace(L"%eps");
480     _constants.emplace(L"%e");
481     _constants.emplace(L"%i");
482     _constants.emplace(L"%nan");
483     _constants.emplace(L"%inf");
484     _constants.emplace(L"%t");
485     _constants.emplace(L"%f");
486     _constants.emplace(L"%T");
487     _constants.emplace(L"%F");
488     _constants.emplace(L"SCI");
489     _constants.emplace(L"WSCI");
490     _constants.emplace(L"SCIHOME");
491     _constants.emplace(L"TMPDIR");
492
493     return _constants;
494 }
495 }