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