Analysis: add info about $ and fix bug
[scilab.git] / scilab / modules / ast / src / cpp / analysis / VisitMatrixExp.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 "tools.hxx"
15
16 namespace analysis
17 {
18 void AnalysisVisitor::visit(ast::MatrixExp & e)
19 {
20     logger.log(L"MatrixExp", e.getLocation());
21     const ast::exps_t & lines = e.getLines();
22     if (lines.empty())
23     {
24         // empty matrix
25         TIType type(getGVN(), TIType::EMPTY);
26         e.getDecorator().res = Result(type);
27         setResult(e.getDecorator().res);
28         return;
29     }
30
31     std::vector<std::pair<int, ast::Exp *>> tempIds;
32     GVN::Value * totalColsRef = nullptr;
33     GVN::Value * totalRows = getGVN().getValue(0.);
34     TIType::Type baseType = TIType::UNKNOWN;
35     bool baseTypeSet = false;
36     bool checkDims = true;
37
38     for (auto line : lines)
39     {
40         const ast::exps_t & columns = static_cast<ast::MatrixLineExp *>(line)->getColumns();
41         if (!columns.empty())
42         {
43             GVN::Value * totalCols = nullptr;
44             GVN::Value * rows = nullptr;
45             for (auto e : columns)
46             {
47                 e->accept(*this);
48                 Result & res = getResult();
49                 TIType & type = res.getType();
50                 const int tempId = res.getTempId();
51                 if (tempId != -1)
52                 {
53                     tempIds.emplace_back(tempId, e);
54                 }
55                 if (type.type != TIType::EMPTY && type.rows != 0 && type.cols != 0)
56                 {
57                     if (!baseTypeSet)
58                     {
59                         baseTypeSet = true;
60                         baseType = type.type;
61                     }
62                     else
63                     {
64                         switch (baseType)
65                         {
66                             case TIType::DOUBLE:
67                                 switch (type.type)
68                                 {
69                                     case TIType::COMPLEX:
70                                         baseType = TIType::COMPLEX;
71                                         break;
72                                     case TIType::DOUBLE:
73                                     case TIType::BOOLEAN:
74                                         break;
75                                     default:
76                                         baseType = TIType::UNKNOWN;
77                                 }
78                                 break;
79                             case TIType::COMPLEX:
80                                 switch (type.type)
81                                 {
82                                     case TIType::DOUBLE:
83                                     case TIType::COMPLEX:
84                                     case TIType::BOOLEAN:
85                                         break;
86                                     default:
87                                         baseType = TIType::UNKNOWN;
88                                 }
89                                 break;
90                             case TIType::BOOLEAN:
91                                 switch (type.type)
92                                 {
93                                     case TIType::DOUBLE:
94                                     case TIType::COMPLEX:
95                                         baseType = type.type;
96                                         break;
97                                     case TIType::BOOLEAN:
98                                         break;
99                                     default:
100                                         baseType = TIType::UNKNOWN;
101                                 }
102                                 break;
103                             default:
104                                 if (baseType != type.type)
105                                 {
106                                     baseType = TIType::UNKNOWN;
107                                 }
108                         }
109                     }
110
111                     if (checkDims)
112                     {
113                         if (!rows)
114                         {
115                             rows = type.rows.getValue();
116                         }
117                         else
118                         {
119                             if (!getCM().check(ConstraintManager::EQUAL, rows, type.rows.getValue()))
120                             {
121                                 checkDims = false;
122                             }
123                         }
124                         if (!totalCols)
125                         {
126                             totalCols = type.cols.getValue();
127                         }
128                         else
129                         {
130                             totalCols = getGVN().getValue(OpValue::Kind::PLUS, *totalCols, *type.cols.getValue());
131                         }
132                     }
133                 }
134             }
135
136             if (checkDims && totalCols)
137             {
138                 if (!totalColsRef)
139                 {
140                     totalColsRef = totalCols;
141                 }
142                 else
143                 {
144                     if (!getCM().check(ConstraintManager::EQUAL, totalCols, totalColsRef))
145                     {
146                         checkDims = false;
147                     }
148                 }
149
150                 if (rows)
151                 {
152                     totalRows = getGVN().getValue(OpValue::Kind::PLUS, *totalRows, *rows);
153                 }
154             }
155         }
156     }
157
158     for (const auto & p : tempIds)
159     {
160         getDM().releaseTmp(p.first, p.second);
161     }
162
163     if (checkDims)
164     {
165         if (!totalRows || !totalColsRef || totalRows->poly->isConstant(0) || totalColsRef->poly->isConstant(0))
166         {
167             TIType type(getGVN(), TIType::EMPTY);
168             e.getDecorator().res = Result(type);
169         }
170         else
171         {
172             TIType type(getGVN(), baseType, SymbolicDimension(getGVN(), totalRows), SymbolicDimension(getGVN(), totalColsRef));
173             e.getDecorator().res = Result(type);
174         }
175     }
176     else
177     {
178         TIType type(getGVN(), baseType, false);
179         e.getDecorator().res = Result(type);
180     }
181
182     setResult(e.getDecorator().res);
183 }
184 }