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