1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2014 - Scilab Enterprises - Calixte DENIZET
4 *
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
6 *
7 * This file is hereby licensed under the terms of the GNU GPL v2.0,
8 * pursuant to article 5.3.4 of the CeCILL v.2.1.
9 * This file was originally licensed under the terms of the CeCILL v2.1,
10 * and continues to be available under such terms.
11 * For more information, see the COPYING file which you should have received
12 * along with this program.
13 *
14 */
15
16 #include "AnalysisVisitor.hxx"
17 #include "tools.hxx"
18
19 namespace analysis
20 {
21
visit(ast::ListExp & e)22 void AnalysisVisitor::visit(ast::ListExp & e)
23 {
24 logger.log(L"ListExp", e.getLocation());
25 if (e.getParent()->isVarDec())
26 {
27 visitInVarDecCtxt(e);
28 return;
29 }
30
31 e.getStart().accept(*this);
32 Result & Rstart = e.getStart().getDecorator().getResult();
33 e.getEnd().accept(*this);
34 Result & Rend = e.getEnd().getDecorator().getResult();
35 e.getStep().accept(*this);
36 Result & Rstep = e.getStep().getDecorator().getResult();
37
38 double start = 1;
39 double step = 1;
40 double end = 1;
41 if (Rstart.getConstant().getDblValue(start) && Rstep.getConstant().getDblValue(step) && Rend.getConstant().getDblValue(end))
42 {
43 // Start, Step & End are constant !
44 double out;
45 int type = ForList64::checkList(start, end, step, out);
46
47 switch (type)
48 {
49 case 0:
50 e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
51 break;
52 case 1:
53 e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::DOUBLE), -1));
54 break;
55 case 2:
56 {
57 const uint64_t N = ForList64::size(start, end, step);
58 TIType T(dm.getGVN(), TIType::DOUBLE, 1, N);
59 if (N == 1)
60 {
61 out = start;
62 }
63 e.getDecorator().setResult(Result(T, dm.getTmpId(T, false)));
64 break;
65 }
66 default:
67 break;
68 }
69 e.setValues(start, step, end, out);
70 setResult(e.getDecorator().res);
71
72 return;
73 }
74
75 if (step == 0 || tools::isNaN(step) || !tools::isFinite(step)
76 || tools::isNaN(start) || !tools::isFinite(start)
77 || tools::isNaN(end) || !tools::isFinite(end))
78 {
79 e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
80 return;
81 }
82
83 if (!Rstep.getConstant().getDblValue(step) || (step != -1 && step != 1))
84 {
85 Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
86 setResult(res);
87 return;
88 }
89
90 if (!Rstart.getType().isscalar() || !Rend.getType().isscalar())
91 {
92 Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
93 setResult(res);
94 return;
95 }
96
97 GVN::Value * gvnStart;
98 if (Rstart.getConstant().getDblValue(start))
99 {
100 if (tools::getIntType(start) == tools::NOTANINT)
101 {
102 gvnStart = getGVN().getValue((double)tools::cast<int>(start + step));
103 }
104 else
105 {
106 gvnStart = getGVN().getValue((double)tools::cast<int>(start));
107 }
108 }
109 else
110 {
111 gvnStart = Rstart.getConstant().getGVNValue();
112 if (!gvnStart)
113 {
114 Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
115 setResult(res);
116 return;
117 }
118 }
119
120 GVN::Value * gvnEnd;
121
122 if (Rend.getConstant().getDblValue(end))
123 {
124 if (tools::getIntType(end) == tools::NOTANINT)
125 {
126 gvnEnd = getGVN().getValue((double)tools::cast<int>(end - step));
127 }
128 else
129 {
130 gvnEnd = getGVN().getValue((double)tools::cast<int>(end));
131 }
132 }
133 else
134 {
135 gvnEnd = Rend.getConstant().getGVNValue();
136 if (!gvnEnd)
137 {
138 Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
139 setResult(res);
140 return;
141 }
142 }
143
144 GVN::Value * ONEValue = getGVN().getValue(int64_t(1));
145 SymbolicDimension ONE(getGVN(), ONEValue);
146 GVN::Value * v;
147
148 if (gvnStart->value == gvnEnd->value)
149 {
150 Result & res = e.getDecorator().setResult(Result(TIType(getGVN(), TIType::DOUBLE, ONE, ONE)));
151 setResult(res);
152 return;
153 }
154
155 if (step == 1)
156 {
157 v = getGVN().getValue(OpValue::Kind::MINUS, *gvnEnd, *gvnStart);
158 }
159 else
160 {
161 v = getGVN().getValue(OpValue::Kind::MINUS, *gvnStart, *gvnEnd);
162 }
163 v = getGVN().getValue(OpValue::Kind::PLUS, *v, *ONEValue);
164
165 if (v->poly->constant < 0 && v->poly->isCoeffNegative(false))
166 {
167 TIType type(getGVN(), TIType::EMPTY);
168 e.getDecorator().res = Result(type);
169 }
170 else
171 {
172 bool res = getCM().check(ConstraintManager::POSITIVE, v);
173 if (res)
174 {
175 TIType type(getGVN(), TIType::DOUBLE, ONE, SymbolicDimension(getGVN(), v));
176 e.getDecorator().setResult(type);
177 }
178 else
179 {
180 Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
181 setResult(res);
182 return;
183 }
184 }
185
186 setResult(e.getDecorator().res);
187 }
188
visitInVarDecCtxt(ast::ListExp & e)189 void AnalysisVisitor::visitInVarDecCtxt(ast::ListExp & e)
190 {
191 e.getStart().accept(*this);
192 Result & Rstart = e.getStart().getDecorator().getResult();
193 e.getEnd().accept(*this);
194 Result & Rend = e.getEnd().getDecorator().getResult();
195 e.getStep().accept(*this);
196 Result & Rstep = e.getStep().getDecorator().getResult();
197
198 double start = 1;
199 double step = 1;
200 double end = 1;
201 if ((Rstart.getConstant().getDblValue(start) || Rstep.getConstant().getDblValue(step)
202 || Rend.getConstant().getDblValue(end)) &&
203 (step == 0 || tools::isNaN(step) || !tools::isFinite(step)
204 || tools::isNaN(start) || !tools::isFinite(start)
205 || tools::isNaN(end) || !tools::isFinite(end)))
206 {
207 // We have an invalid list
208 e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
209 return;
210 }
211
212 ast::VarDec & vd = *static_cast<ast::VarDec *>(e.getParent());
213 const symbol::Symbol & sym = vd.getSymbol();
214 GVN::Value * startRange = nullptr;
215 GVN::Value * endRange = nullptr;
216 Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::DOUBLE), -1));
217
218 if (Rstart.getConstant().getGVNValue(getGVN(), startRange) && Rend.getConstant().getGVNValue(getGVN(), endRange))
219 {
220 // Start & End are GVN values
221 res.setRange(SymbolicRange(getGVN(), startRange, endRange));
222 }
223 else
224 {
225 SymbolicRange & rangeStart = Rstart.getRange();
226 if (rangeStart.isValid())
227 {
228 // Start is an iterator: for i=1:N, for j=i:N, ... in the second for "i" in "i:n" is an iterator
229 if (endRange || Rend.getConstant().getGVNValue(getGVN(), endRange))
230 {
231 // Start is an iterator and End is GVN value
232 res.setRange(SymbolicRange(getGVN(), rangeStart.getStart(), endRange));
233 }
234 else
235 {
236 SymbolicRange & rangeEnd = Rend.getRange();
237 if (rangeEnd.isValid())
238 {
239 // Start & End are iterators
240 res.setRange(SymbolicRange(getGVN(), rangeStart.getStart(), rangeEnd.getEnd()));
241 }
242 }
243 }
244 else if (startRange || Rstart.getConstant().getGVNValue(getGVN(), startRange))
245 {
246 // Start is a GVN value
247 SymbolicRange & rangeEnd = Rend.getRange();
248 if (rangeEnd.isValid())
249 {
250 // Start is a GVN value and End is an iterator
251 res.setRange(SymbolicRange(getGVN(), startRange, rangeEnd.getEnd()));
252 }
253 }
254 }
255
256 setResult(res);
257 }
258 }
259