Analysis: replace constant in Result by a C++ union
[scilab.git] / scilab / modules / ast / src / cpp / analysis / SizeAnalyzer.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/SizeAnalyzer.hxx"
15 #include "tools.hxx"
16
17 namespace analysis
18 {
19 bool SizeAnalyzer::analyze(AnalysisVisitor & visitor, const unsigned int lhs, ast::CallExp & e)
20 {
21     if (lhs > 2)
22     {
23         return false;
24     }
25
26     const ast::exps_t args = e.getArgs();
27     enum Kind
28     {
29         ROWS, COLS, ROWSTIMESCOLS, ROWSCOLS, ONE
30     } kind;
31     const std::size_t size = args.size();
32     if (size == 0 || size >= 3)
33     {
34         return false;
35     }
36
37     ast::Exp * first = *args.begin();
38     if (!first)
39     {
40         return false;
41     }
42     first->accept(visitor);
43     Result & res = visitor.getResult();
44     if (!res.getType().ismatrix())
45     {
46         return false;
47     }
48
49     switch (size)
50     {
51         case 1:
52             if (lhs == 1)
53             {
54                 kind = ROWS;
55             }
56             else if (lhs == 2)
57             {
58                 kind = ROWSCOLS;
59             }
60             break;
61         case 2:
62         {
63             ast::Exp * second = *std::next(args.begin());
64             if (second && lhs == 1)
65             {
66                 if (second->isStringExp())
67                 {
68                     const std::wstring & arg2 = static_cast<ast::StringExp *>(second)->getValue();
69                     if (arg2 == L"r")
70                     {
71                         kind = ROWS;
72                     }
73                     else if (arg2 == L"c")
74                     {
75                         kind = COLS;
76                     }
77                     else if (arg2 == L"*")
78                     {
79                         kind = ROWSTIMESCOLS;
80                     }
81                     else
82                     {
83                         return false;
84                     }
85                 }
86                 else if (second->isDoubleExp())
87                 {
88                     const double arg2 = static_cast<ast::DoubleExp *>(second)->getValue();
89                     if (arg2 == 1)
90                     {
91                         kind = ROWS;
92                     }
93                     else if (arg2 == 2)
94                     {
95                         kind = COLS;
96                     }
97                     else if (arg2 >= 3)
98                     {
99                         kind = ONE;
100                     }
101                     else
102                     {
103                         return false;
104                     }
105                 }
106             }
107             else
108             {
109                 return false;
110             }
111             break;
112         }
113         default:
114             return false;
115     }
116
117     TIType type(visitor.getGVN(), TIType::DOUBLEUINT);
118
119     switch (kind)
120     {
121         case ROWS:
122         {
123             SymbolicDimension & rows = res.getType().rows;
124             Result & _res = e.getDecorator().setResult(type);
125             _res.getConstant().set(rows.getValue());
126             e.getDecorator().setCall(Call(Call::IDENTITY, type, L"size"));
127             visitor.setResult(_res);
128             break;
129         }
130         case COLS:
131         {
132             SymbolicDimension & cols = res.getType().cols;
133             Result & _res = e.getDecorator().setResult(type);
134             _res.getConstant().set(cols.getValue());
135             e.getDecorator().setCall(Call(Call::IDENTITY, type, L"size"));
136             visitor.setResult(_res);
137             break;
138         }
139         case ROWSTIMESCOLS:
140         {
141             SymbolicDimension & rows = res.getType().rows;
142             SymbolicDimension & cols = res.getType().cols;
143             SymbolicDimension prod = rows * cols;
144             Result & _res = e.getDecorator().setResult(type);
145             _res.getConstant().set(prod.getValue());
146             e.getDecorator().setCall(Call(Call::IDENTITY, type, L"size"));
147             visitor.setResult(_res);
148             break;
149         }
150         case ROWSCOLS:
151         {
152             SymbolicDimension & rows = res.getType().rows;
153             SymbolicDimension & cols = res.getType().cols;
154             std::vector<Result> & mlhs = visitor.getLHSContainer();
155             mlhs.clear();
156             mlhs.reserve(2);
157             mlhs.emplace_back(type);
158             mlhs.back().getConstant().set(rows.getValue());
159             mlhs.emplace_back(type);
160             mlhs.back().getConstant().set(cols.getValue());
161
162             e.getDecorator().setCall(Call(Call::IDENTITY, type, L"size"));
163             break;
164         }
165     }
166
167     return true;
168 }
169 }