Analysis: enable symbolic analysis of the matrice dimensions
[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 void AnalysisVisitor::visit(ast::ListExp & e)
19 {
20     double start, step, end;
21     if (AnalysisVisitor::asDouble(e.getStart(), start) && AnalysisVisitor::asDouble(e.getStep(), step) && AnalysisVisitor::asDouble(e.getEnd(), end))
22     {
23         double out;
24         int type = ForList64::checkList(start, end, step, out);
25
26         switch (type)
27         {
28             case 0:
29                 e.getDecorator().res = Result(TIType(dm.getGVN(), TIType::EMPTY), -1);
30                 break;
31             case 1:
32                 e.getDecorator().res = Result(TIType(dm.getGVN(), TIType::DOUBLE), -1);
33                 break;
34             case 2:
35             {
36                 const uint64_t N = ForList64::size(start, end, step);
37                 TIType T(dm.getGVN(), TIType::DOUBLE, 1, N);
38                 if (N == 1)
39                 {
40                     out = start;
41                 }
42                 e.getDecorator().res = Result(T, temp.add(T));
43                 break;
44             }
45             default:
46                 break;
47         }
48         e.setValues(start, step, end, out);
49         setResult(e.getDecorator().res);
50
51         return;
52     }
53
54     e.getStart().accept(*this);
55     Result Rstart = getResult();
56
57     if (!AnalysisVisitor::asDouble(e.getStep(), step) || (step != -1 && step != 1))
58     {
59         e.getDecorator().res = Result(TIType(dm.getGVN(), Rstart.getType().type, false, true), -1);
60         setResult(e.getDecorator().res);
61
62         return;
63     }
64
65     GVN::Value * gvnStart;
66
67     if (!Rstart.getType().isscalar())
68     {
69         e.getDecorator().res = Result(TIType(dm.getGVN(), Rstart.getType().type, false, true), -1);
70         setResult(e.getDecorator().res);
71
72         return;
73     }
74
75     if (Rstart.getValue(start))
76     {
77         if (Rstart.getIntType() == tools::NOTANINT)
78         {
79             gvnStart = getGVN().getValue((double)tools::cast<int>(start + step));
80         }
81         else
82         {
83             gvnStart = getGVN().getValue((double)tools::cast<int>(start));
84         }
85     }
86     else
87     {
88         gvnStart = Rstart.getGVNValue();
89         if (!gvnStart)
90         {
91             e.getDecorator().res = Result(TIType(dm.getGVN(), Rstart.getType().type, false, true), -1);
92             setResult(e.getDecorator().res);
93
94             return;
95         }
96     }
97
98     e.getEnd().accept(*this);
99     Result & Rend = getResult();
100     GVN::Value * gvnEnd;
101
102     if (Rend.getValue(end))
103     {
104         if (Rend.getIntType() == tools::NOTANINT)
105         {
106             gvnEnd = getGVN().getValue((double)tools::cast<int>(end - step));
107         }
108         else
109         {
110             gvnEnd = getGVN().getValue((double)tools::cast<int>(end));
111         }
112     }
113     else
114     {
115         gvnEnd = Rend.getGVNValue();
116         if (!gvnEnd)
117         {
118             e.getDecorator().res = Result(TIType(dm.getGVN(), Rstart.getType().type, false, true), -1);
119             setResult(e.getDecorator().res);
120
121             return;
122         }
123     }
124
125     GVN::Value * ONEValue = getGVN().getValue(1.);
126     SymbolicDimension ONE(getGVN(), ONEValue);
127     GVN::Value * v;
128     if (step == 1)
129     {
130         v = getGVN().getValue(OpValue::Kind::MINUS, *gvnEnd, *gvnStart);
131     }
132     else
133     {
134         v = getGVN().getValue(OpValue::Kind::MINUS, *gvnStart, *gvnEnd);
135     }
136     v = getGVN().getValue(OpValue::Kind::PLUS, *v, *ONEValue);
137
138     if (v->poly->isConstant() && v->poly->constant <= 0)
139     {
140         TIType type(getGVN(), TIType::EMPTY);
141         e.getDecorator().res = Result(type);
142     }
143     else
144     {
145         bool res = getCM().check(ConstraintManager::POSITIVE, v);
146         if (res)
147         {
148             TIType type(getGVN(), TIType::DOUBLE, ONE, SymbolicDimension(getGVN(), v));
149             e.getDecorator().res = Result(type);
150         }
151         else
152         {
153             e.getDecorator().res = Result(TIType(dm.getGVN(), Rstart.getType().type, false, true), -1);
154             setResult(e.getDecorator().res);
155
156             return;
157         }
158     }
159     setResult(e.getDecorator().res);
160 }
161 }