Analysis: always a WIP but we would expect that the end is nearer than the begin
[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 = getResult();
24         e.getEnd().accept(*this);
25         Result Rend = getResult();
26         e.getStep().accept(*this);
27         Result & Rstep = getResult();
28
29         if (e.getParent()->isVarDec())
30         {
31             GVN::Value * startRange;
32             GVN::Value * endRange;
33             if (Rstart.getConstant().getGVNValue(getGVN(), startRange) && Rend.getConstant().getGVNValue(getGVN(), endRange))
34             {
35                 const symbol::Symbol & sym = static_cast<ast::VarDec *>(e.getParent())->getSymbol();
36                 TIType typ(dm.getGVN(), TIType::DOUBLE);
37                 Result & res = e.getDecorator().setResult(Result(typ, -1));
38                 res.setRange(SymbolicRange(getGVN(), startRange, endRange));
39                 setResult(res);
40                 return;
41             }
42         }
43         
44         double start, step, end;
45         if (Rstart.getConstant().getDblValue(start) && Rstep.getConstant().getDblValue(step) && Rend.getConstant().getDblValue(end))
46         {
47             double out;
48             int type = ForList64::checkList(start, end, step, out);
49
50             switch (type)
51             {
52             case 0:
53                 e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
54                 break;
55             case 1:
56                 e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::DOUBLE), -1));
57                 break;
58             case 2:
59             {
60                 const uint64_t N = ForList64::size(start, end, step);
61                 TIType T(dm.getGVN(), TIType::DOUBLE, 1, N);
62                 if (N == 1)
63                 {
64                     out = start;
65                 }
66                 e.getDecorator().setResult(Result(T, temp.add(T)));
67                 break;
68             }
69             default:
70                 break;
71             }
72             e.setValues(start, step, end, out);
73             setResult(e.getDecorator().res);
74
75             return;
76         }
77
78         if (!Rstep.getConstant().getDblValue(step) || (step != -1 && step != 1))
79         {
80             Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
81             setResult(res);
82             return;
83         }
84
85         if (!Rstart.getType().isscalar() || !Rend.getType().isscalar())
86         {
87             Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
88             setResult(res);
89             return;
90         }
91
92         GVN::Value * gvnStart;
93         if (Rstart.getConstant().getDblValue(start))
94         {
95             if (tools::getIntType(start) == tools::NOTANINT)
96             {
97                 gvnStart = getGVN().getValue((double)tools::cast<int>(start + step));
98             }
99             else
100             {
101                 gvnStart = getGVN().getValue((double)tools::cast<int>(start));
102             }
103         }
104         else
105         {
106             gvnStart = Rstart.getConstant().getGVNValue();
107             if (!gvnStart)
108             {
109                 Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
110                 setResult(res);
111                 return;
112             }
113         }
114
115         GVN::Value * gvnEnd;
116
117         if (Rend.getConstant().getDblValue(end))
118         {
119             if (tools::getIntType(end) == tools::NOTANINT)
120             {
121                 gvnEnd = getGVN().getValue((double)tools::cast<int>(end - step));
122             }
123             else
124             {
125                 gvnEnd = getGVN().getValue((double)tools::cast<int>(end));
126             }
127         }
128         else
129         {
130             gvnEnd = Rend.getConstant().getGVNValue();
131             if (!gvnEnd)
132             {
133                 Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
134                 setResult(res);
135                 return;
136             }
137         }
138
139         GVN::Value * ONEValue = getGVN().getValue(1.);
140         SymbolicDimension ONE(getGVN(), ONEValue);
141         GVN::Value * v;
142
143         if (gvnStart->value == gvnEnd->value)
144         {
145             Result & res = e.getDecorator().setResult(Result(TIType(getGVN(), TIType::DOUBLE, ONE, ONE)));
146             setResult(res);
147             return;
148         }
149
150         if (step == 1)
151         {
152             v = getGVN().getValue(OpValue::Kind::MINUS, *gvnEnd, *gvnStart);
153         }
154         else
155         {
156             v = getGVN().getValue(OpValue::Kind::MINUS, *gvnStart, *gvnEnd);
157         }
158         v = getGVN().getValue(OpValue::Kind::PLUS, *v, *ONEValue);
159
160         if (v->poly->constant < 0 && v->poly->isCoeffNegative(false))
161         {
162             TIType type(getGVN(), TIType::EMPTY);
163             e.getDecorator().res = Result(type);
164         }
165         else
166         {
167             bool res = getCM().check(ConstraintManager::POSITIVE, v);
168             if (res)
169             {
170                 TIType type(getGVN(), TIType::DOUBLE, ONE, SymbolicDimension(getGVN(), v));
171                 e.getDecorator().setResult(type);
172             }
173             else
174             {
175                 Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
176                 setResult(res);
177                 return;
178             }
179         }
180
181         setResult(e.getDecorator().res);
182     }
183 }