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