Analysis: fix bug in listexp when in a vardec
[scilab.git] / scilab / modules / ast / src / cpp / analysis / ArgnAnalyzer.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 "analyzers/ArgnAnalyzer.hxx"
15 #include "tools.hxx"
16 #include "double.hxx"
17
18 namespace analysis
19 {
20 bool ArgnAnalyzer::analyze(AnalysisVisitor & visitor, const unsigned int lhs, ast::CallExp & e)
21 {
22     if (lhs > 2)
23     {
24         return false;
25     }
26
27     TIType type(visitor.getGVN(), TIType::DOUBLE);
28     FunctionBlock * fblock = visitor.getDM().topFunction();
29     if (!fblock)
30     {
31         if (lhs == 1)
32         {
33             Result & res = e.getDecorator().setResult(type);
34             res.getConstant() = new types::Double(0);
35             e.getDecorator().setCall(L"argn");
36             visitor.setResult(res);
37             return true;
38         }
39         return false;
40     }
41
42
43     enum Kind 
44     {
45         LHS, RHS, LHSRHS
46     } kind;
47     const ast::exps_t args = e.getArgs();
48     switch (args.size())
49     {
50         case 0:
51         {
52             if (lhs == 1)
53             {
54                 kind = LHS;
55             }
56             else if (lhs == 2)
57             {
58                 kind = LHSRHS;
59             }
60             break;
61         }
62         case 1:
63         {
64             ast::Exp * first = args.front();
65             if (first && first->isDoubleExp())
66             {
67                 const double arg1 = static_cast<ast::DoubleExp *>(first)->getValue();
68                 if (arg1 == 0)
69                 {
70                     if (lhs == 1)
71                     {
72                         kind = LHS;
73                     }
74                     else if (lhs == 2)
75                     {
76                         kind = LHSRHS;
77                     }
78                 }
79                 else if (arg1 == 1)
80                 {
81                     kind = LHS;
82                 }
83                 else if (arg1 == 2)
84                 {
85                     kind = RHS;
86                 }
87                 else
88                 {
89                     return false;
90                 }
91             }
92             else
93             {
94                 return false;
95             }
96             break;
97         }
98         default:
99             return false;
100     }
101
102     switch (kind)
103     {
104         case LHS:
105         case RHS:
106         {
107             const int64_t val = kind == LHS ? fblock->getLHS() : fblock->getRHS();
108             Result & res = e.getDecorator().setResult(type);
109             res.getConstant() = visitor.getGVN().getValue(val);
110             e.getDecorator().setCall(L"argn");
111             visitor.setResult(res);
112         }
113         case LHSRHS:
114         {
115             std::vector<Result> & mlhs = visitor.getLHSContainer();
116             mlhs.clear();
117             mlhs.reserve(2);
118
119             const int64_t flhs = fblock->getLHS();
120             const int64_t frhs = fblock->getRHS();
121             mlhs.emplace_back(type);
122             mlhs.back().getConstant() = visitor.getGVN().getValue(flhs);
123             mlhs.emplace_back(type);
124             mlhs.back().getConstant() = visitor.getGVN().getValue(frhs);
125
126             e.getDecorator().setCall(L"argn");
127         }
128     }
129
130     return true;
131 }
132 }