Analysis: fix bug in listexp analysis
[scilab.git] / scilab / modules / ast / src / cpp / analysis / VisitListExp.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
19 void AnalysisVisitor::visit(ast::ListExp & e)
20 {
21     logger.log(L"ListExp", e.getLocation());
22     e.getStart().accept(*this);
23     Result & Rstart = e.getStart().getDecorator().getResult();
24     e.getEnd().accept(*this);
25     Result & Rend = e.getEnd().getDecorator().getResult();
26     e.getStep().accept(*this);
27     Result & Rstep = e.getStep().getDecorator().getResult();
28
29     if (e.getParent()->isVarDec())
30     {
31         ast::VarDec & vd = *static_cast<ast::VarDec *>(e.getParent());
32         const symbol::Symbol & sym = vd.getSymbol();
33         GVN::Value * startRange = nullptr;
34         GVN::Value * endRange = nullptr;
35         if (Rstart.getConstant().getGVNValue(getGVN(), startRange) && Rend.getConstant().getGVNValue(getGVN(), endRange))
36         {
37             TIType typ(dm.getGVN(), TIType::DOUBLE);
38             Result & res = e.getDecorator().setResult(Result(typ, -1));
39             res.setRange(SymbolicRange(getGVN(), startRange, endRange));
40             setResult(res);
41             return;
42         }
43         SymbolicRange & rangeStart = Rstart.getRange();
44         if (rangeStart.isValid())
45         {
46             if (endRange || Rend.getConstant().getGVNValue(getGVN(), endRange))
47             {
48                 // start is an iterator and end is not
49                 TIType typ(dm.getGVN(), TIType::DOUBLE);
50                 Result & res = e.getDecorator().setResult(Result(typ, -1));
51                 res.setRange(SymbolicRange(getGVN(), rangeStart.getStart(), endRange));
52                 setResult(res);
53                 return;
54             }
55             else
56             {
57                 SymbolicRange & rangeEnd = Rend.getRange();
58                 if (rangeEnd.isValid())
59                 {
60                     TIType typ(dm.getGVN(), TIType::DOUBLE);
61                     Result & res = e.getDecorator().setResult(Result(typ, -1));
62                     res.setRange(SymbolicRange(getGVN(), rangeStart.getStart(), rangeEnd.getEnd()));
63                     setResult(res);
64                     return;
65                 }
66             }
67         }
68         // TODO: finish all the cases
69     }
70
71     double start = 1;
72     double step = 1;
73     double end = 1;
74     if (Rstart.getConstant().getDblValue(start) && Rstep.getConstant().getDblValue(step) && Rend.getConstant().getDblValue(end))
75     {
76         double out;
77         int type = ForList64::checkList(start, end, step, out);
78
79         switch (type)
80         {
81             case 0:
82                 e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
83                 break;
84             case 1:
85                 e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::DOUBLE), -1));
86                 break;
87             case 2:
88             {
89                 const uint64_t N = ForList64::size(start, end, step);
90                 if (e.getParent()->isVarDec())
91                 {
92                     TIType T(dm.getGVN(), TIType::DOUBLE, 1, 1);
93                     e.getDecorator().setResult(Result(T));
94                 }
95                 else
96                 {
97                     TIType T(dm.getGVN(), TIType::DOUBLE, 1, N);
98                     if (N == 1)
99                     {
100                         out = start;
101                     }
102                     e.getDecorator().setResult(Result(T, dm.getTmpId(T, false)));
103                 }
104                 break;
105             }
106             default:
107                 break;
108         }
109         e.setValues(start, step, end, out);
110         setResult(e.getDecorator().res);
111
112         return;
113     }
114
115     if (step == 0 || tools::isNaN(step) || !tools::isFinite(step)
116             || tools::isNaN(start) || !tools::isFinite(start)
117             ||  tools::isNaN(end) || !tools::isFinite(end))
118     {
119         e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
120         return;
121     }
122
123     if (!Rstep.getConstant().getDblValue(step) || (step != -1 && step != 1))
124     {
125         Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
126         setResult(res);
127         return;
128     }
129
130     if (!Rstart.getType().isscalar() || !Rend.getType().isscalar())
131     {
132         Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
133         setResult(res);
134         return;
135     }
136
137     GVN::Value * gvnStart;
138     if (Rstart.getConstant().getDblValue(start))
139     {
140         if (tools::getIntType(start) == tools::NOTANINT)
141         {
142             gvnStart = getGVN().getValue((double)tools::cast<int>(start + step));
143         }
144         else
145         {
146             gvnStart = getGVN().getValue((double)tools::cast<int>(start));
147         }
148     }
149     else
150     {
151         gvnStart = Rstart.getConstant().getGVNValue();
152         if (!gvnStart)
153         {
154             Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
155             setResult(res);
156             return;
157         }
158     }
159
160     GVN::Value * gvnEnd;
161
162     if (Rend.getConstant().getDblValue(end))
163     {
164         if (tools::getIntType(end) == tools::NOTANINT)
165         {
166             gvnEnd = getGVN().getValue((double)tools::cast<int>(end - step));
167         }
168         else
169         {
170             gvnEnd = getGVN().getValue((double)tools::cast<int>(end));
171         }
172     }
173     else
174     {
175         gvnEnd = Rend.getConstant().getGVNValue();
176         if (!gvnEnd)
177         {
178             Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
179             setResult(res);
180             return;
181         }
182     }
183
184     GVN::Value * ONEValue = getGVN().getValue(1);
185     SymbolicDimension ONE(getGVN(), ONEValue);
186     GVN::Value * v;
187
188     if (gvnStart->value == gvnEnd->value)
189     {
190         Result & res = e.getDecorator().setResult(Result(TIType(getGVN(), TIType::DOUBLE, ONE, ONE)));
191         setResult(res);
192         return;
193     }
194
195     if (step == 1)
196     {
197         v = getGVN().getValue(OpValue::Kind::MINUS, *gvnEnd, *gvnStart);
198     }
199     else
200     {
201         v = getGVN().getValue(OpValue::Kind::MINUS, *gvnStart, *gvnEnd);
202     }
203     v = getGVN().getValue(OpValue::Kind::PLUS, *v, *ONEValue);
204
205     if (v->poly->constant < 0 && v->poly->isCoeffNegative(false))
206     {
207         TIType type(getGVN(), TIType::EMPTY);
208         e.getDecorator().res = Result(type);
209     }
210     else
211     {
212         bool res = getCM().check(ConstraintManager::POSITIVE, v);
213         if (res)
214         {
215             TIType type(getGVN(), TIType::DOUBLE, ONE, SymbolicDimension(getGVN(), v));
216             e.getDecorator().setResult(type);
217         }
218         else
219         {
220             Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
221             setResult(res);
222             return;
223         }
224     }
225
226     setResult(e.getDecorator().res);
227 }
228 }