6cb6670429bbca016670e8beaaaaa91725574b84
[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, step, end;
72     if (Rstart.getConstant().getDblValue(start) && Rstep.getConstant().getDblValue(step) && Rend.getConstant().getDblValue(end))
73     {
74         double out;
75         int type = ForList64::checkList(start, end, step, out);
76
77         switch (type)
78         {
79             case 0:
80                 e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
81                 break;
82             case 1:
83                 e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::DOUBLE), -1));
84                 break;
85             case 2:
86             {
87                 const uint64_t N = ForList64::size(start, end, step);
88                 TIType T(dm.getGVN(), TIType::DOUBLE, 1, N);
89                 if (N == 1)
90                 {
91                     out = start;
92                 }
93                 e.getDecorator().setResult(Result(T, dm.getTmpId(T, false)));
94                 break;
95             }
96             default:
97                 break;
98         }
99         e.setValues(start, step, end, out);
100         setResult(e.getDecorator().res);
101
102         return;
103     }
104
105     if (!Rstep.getConstant().getDblValue(step) || (step != -1 && step != 1))
106     {
107         Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
108         setResult(res);
109         return;
110     }
111
112     if (!Rstart.getType().isscalar() || !Rend.getType().isscalar())
113     {
114         Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
115         setResult(res);
116         return;
117     }
118
119     GVN::Value * gvnStart;
120     if (Rstart.getConstant().getDblValue(start))
121     {
122         if (tools::getIntType(start) == tools::NOTANINT)
123         {
124             gvnStart = getGVN().getValue((double)tools::cast<int>(start + step));
125         }
126         else
127         {
128             gvnStart = getGVN().getValue((double)tools::cast<int>(start));
129         }
130     }
131     else
132     {
133         gvnStart = Rstart.getConstant().getGVNValue();
134         if (!gvnStart)
135         {
136             Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
137             setResult(res);
138             return;
139         }
140     }
141
142     GVN::Value * gvnEnd;
143
144     if (Rend.getConstant().getDblValue(end))
145     {
146         if (tools::getIntType(end) == tools::NOTANINT)
147         {
148             gvnEnd = getGVN().getValue((double)tools::cast<int>(end - step));
149         }
150         else
151         {
152             gvnEnd = getGVN().getValue((double)tools::cast<int>(end));
153         }
154     }
155     else
156     {
157         gvnEnd = Rend.getConstant().getGVNValue();
158         if (!gvnEnd)
159         {
160             Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
161             setResult(res);
162             return;
163         }
164     }
165
166     GVN::Value * ONEValue = getGVN().getValue(1);
167     SymbolicDimension ONE(getGVN(), ONEValue);
168     GVN::Value * v;
169
170     if (gvnStart->value == gvnEnd->value)
171     {
172         Result & res = e.getDecorator().setResult(Result(TIType(getGVN(), TIType::DOUBLE, ONE, ONE)));
173         setResult(res);
174         return;
175     }
176
177     if (step == 1)
178     {
179         v = getGVN().getValue(OpValue::Kind::MINUS, *gvnEnd, *gvnStart);
180     }
181     else
182     {
183         v = getGVN().getValue(OpValue::Kind::MINUS, *gvnStart, *gvnEnd);
184     }
185     v = getGVN().getValue(OpValue::Kind::PLUS, *v, *ONEValue);
186
187     if (v->poly->constant < 0 && v->poly->isCoeffNegative(false))
188     {
189         TIType type(getGVN(), TIType::EMPTY);
190         e.getDecorator().res = Result(type);
191     }
192     else
193     {
194         bool res = getCM().check(ConstraintManager::POSITIVE, v);
195         if (res)
196         {
197             TIType type(getGVN(), TIType::DOUBLE, ONE, SymbolicDimension(getGVN(), v));
198             e.getDecorator().setResult(type);
199         }
200         else
201         {
202             Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
203             setResult(res);
204             return;
205         }
206     }
207
208     setResult(e.getDecorator().res);
209 }
210 }